using System.Collections.Generic;
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TyMES.Model.BaseInformation;
using WalkingTec.Mvvm.Core;
using Newtonsoft.Json;
using TyMES.PassStationCommunication;
//using TyMES.ViewModel.BaseInformation.RouteOperationVMs;
using TyMES.Model.Record;
using Microsoft.Extensions.Caching.Memory;
using TyMES.Communication;
using TyMES.Model.GetData;
using static TyMES.Communication.FactoryAPIBase;
using Aliyun.OSS;
using System.Configuration;
using System.Text.Json.Serialization;
using Microsoft.EntityFrameworkCore;
using System.Text.RegularExpressions;
using Fluid.Parser;
using System.ComponentModel.DataAnnotations;
using TyMES.Communication.Request;
using static TyMES.Record.Controllers.ProduceDataRecordController;
using Microsoft.AspNetCore.Http.HttpResults;
using TyMES.TemporaryClass;
using Microsoft.AspNetCore.Http;
using Elsa.Models;
using Azure;
using TyMES.DataAccess;
using TyMES.Communication.Response;
using static TyMES.Communication.Response.NormalResponse;
using static TyMES.Communication.Request.UIRequest;
using static TyMES.Communication.Response.UIResponse;
using static Aliyun.OSS.Model.InventoryConfigurationModel;
using static TyMES.Communication.Request.RepairRequest;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System.Net.WebSockets;
using Microsoft.AspNetCore.SignalR;
using TyMES.MidWare;
using System.Reflection;
using TyMES.ViewModel.Record.PassStationRecordVMs;
using TyMES.ViewModel.Record.SkipOperationsVMs;
//using static NPOI.XSSF.UserModel.Charts.XSSFLineChartData<Tx, Ty>;

namespace TyMES.Services
{
    public class PassStationService
    {
        private readonly ILogger logger;
        private readonly IConfiguration configuration;
        private readonly HttpService httpService;
        private readonly IServiceScope serviceScope;
        private readonly IMemoryCache memoryCache;
        private readonly WTMContext context;
        private string factoryCode;
        private string _LineCode;
        private string mesIP;
        private string mesPort;
        private OrderService orderService;
        private readonly CodeCreateService codeCreateService;
        private readonly IHubContext<NotificationHub> notification;
        private readonly IHubContext<InverseControlHub> inverseControl;
        public PassStationService(ILogger<PassStationService> logger, WTMContext context, IConfiguration configuration, HttpService httpService, IServiceScopeFactory serviceScopeFactory, IMemoryCache memoryCache,
            OrderService _orderService, CodeCreateService codeCreateService, IHubContext<NotificationHub> notificationHub, IHubContext<InverseControlHub> inverseControl)
        {
            this.logger = logger;
            this.configuration = configuration;
            this.httpService = httpService;
            this.memoryCache = memoryCache;
            this.context = context;
            this.factoryCode = configuration["FactoryCode"];
            this.mesIP = configuration["MESIP"];
            this.mesPort = configuration["MESPORT"];
            this._LineCode = configuration["LineCode"];
            this.orderService = _orderService;
            this.codeCreateService = codeCreateService;
            this.notification = notificationHub;
            this.inverseControl = inverseControl;
        }


        //与工厂MES交互
        private async Task<T> Call4FactoryMESAsync<U, T>(U requestBody, string url)
        {
            try
            {
                string postData = JsonConvert.SerializeObject(requestBody);
                //记录请求报文
                logger.LogInformation(postData);
                string value = await httpService.PostDataAsync(url, postData);
                //记录响应报文
                logger.LogInformation(value);
                T response = JsonConvert.DeserializeObject<T>(value);
                return response;
            }
            catch (Exception)
            {
                throw;
            }
        }


        private async Task<SNInfo4PackageResponse> Call5FactoryMESAsync(SNInfo4PackageRequest requestBody, string url)
        {
            try
            {
                string postData = JsonConvert.SerializeObject(requestBody);
                //记录请求报文
                logger.LogInformation(postData);
                string value = await httpService.PostDataAsync(url, postData);
                //记录响应报文
                logger.LogInformation(value);
                SNInfo4PackageResponse response = JsonConvert.DeserializeObject<SNInfo4PackageResponse>(value);
                return response;
            }
            catch (Exception)
            {
                throw;
            }
        }
        // ??返回是针对该工单下每个排程的投入数量吗？ 待测试传入具体排程号的返回结果
        //查询投入数量 Product013_ScheduleInPutNumber
        private async Task<ResponseComBase<int>> TryScheduleInPutNumberAsync(ScheduleInPutNumberRequest request)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["ROUTEBOM"];
            try
            {
                ScheduleInPutNumberResponse res = await Call4FactoryMESAsync<ScheduleInPutNumberRequest, ScheduleInPutNumberResponse>(request, url);
                if (res.code == "000000" && res.data.Count > 0)
                {
                    int ans = 0;
                    for (int i = 0; i < res.data.Count; ++i)
                    {
                        if (res.data[i].orderNumber == request.orderNumber && res.data[i].scheduleNum == request.scheduleNumber)
                        {
                            ans = res.data[i].count;
                            break;
                        }
                    }
                    return new ResponseComBase<int>() { Success = true, Mesg = "success", Data = ans };
                }
                else
                {
                    return new ResponseComBase<int>() { Success = false, Mesg = "无投入数据" };
                }
            }
            catch (Exception ex)
            {
                return new ResponseComBase<int>() { Success = false, Mesg = ex.Message };
            }
        }


        //进出站请求 Product003_PassStation
        private async Task<ResponseComBool> TryPassStatoinAsync(PassStationRequest request)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["ROUTEBOM"];

            // 暂时设置为null
            //request.snBindState = null;
            // 暂时设置为null
            //request.trayNumber = null;

            try
            {
                //return new ResponseComBool() { Success = false, Mesg = "暂时屏蔽工厂mes过站" };
                PassStationResponse res = await Call4FactoryMESAsync<PassStationRequest, PassStationResponse>(request, url);
                if (res.code == "000000")
                {
                    return new ResponseComBool() { Success = true, Mesg = res.data };
                }
                else
                {
                    return new ResponseComBool() { Success = false, Mesg = res.mesg };
                }
            }
            catch (Exception ex)
            {
                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }
        }


        //载具绑定 托盘绑定？ Product002_BindVehicle
        public async Task<ResponseComBool> TryBindVehicleAsync(BindVehicleRequest request)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["ROUTEBOM"];

            try
            {
                BindVehicleResponse res = await Call4FactoryMESAsync<BindVehicleRequest, BindVehicleResponse>(request, url);
                if (res.code == "000000")
                {
                    return new ResponseComBool() { Success = true, Mesg = res.code };
                }
                else
                {
                    return new ResponseComBool() { Success = false, Mesg = res.mesg };
                }
            }
            catch (Exception ex)
            {
                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }
        }


        //查询SN基本信息 Base018_SNInfo4Package
        private async Task<ResponseComBase<SNInfo4PackageResponseSup>> TrySNInfo4PackageAsync(SNInfo4PackageRequest request)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["ROUTEBOM"];
            if (request.snNumber == "")
            {
                return new ResponseComBase<SNInfo4PackageResponseSup>() { Success = false, Mesg = "SN码不能为空" };
            }
            try
            {
                SNInfo4PackageResponse res = await Call4FactoryMESAsync<SNInfo4PackageRequest, SNInfo4PackageResponse>(request, url);
                if (res.code == "000000" && res.data.Count > 0)
                {
                    return new ResponseComBase<SNInfo4PackageResponseSup>() { Success = true, Mesg = "success", Data = res.data[0] };
                }
                else
                {
                    return new ResponseComBase<SNInfo4PackageResponseSup>() { Success = false, Mesg = "无返回信息" };
                }
            }
            catch (Exception ex)
            {
                return new ResponseComBase<SNInfo4PackageResponseSup>() { Success = false, Mesg = "上传SN错误，请检查" };
            }
        }


        //查询工序参数 Base011_ProcessParameters
        private async Task<ResponseComBool> TryProcessParametersAsync(ProcessParametersRequest request)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["ROUTEBOM"];
            try
            {
                ProcessParametersResponse res = await Call4FactoryMESAsync<ProcessParametersRequest, ProcessParametersResponse>(request, url);
                if (res.code == "000000" && res.data.Count() > 0)
                {
                    return new ResponseComBool() { Success = true, Mesg = res.data[0].paramValue };
                }
                else
                {
                    return new ResponseComBool() { Success = false, Mesg = res.mesg };
                }
            }
            catch (Exception ex)
            {
                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }
        }

        //首站进站
        public async Task<ResponseComBool> PassFirstStationInAsync(PassStationRequest request, int inputNum, int scheduleNum, BindVehicleRequest request2)
        {
            int inputNumCur;
            var inputNumRes = await CheckOutputNumber(request, inputNum);

            //记录工厂MES投入数量，返回结果异常时以产线记录为标准
            if (inputNumRes.Success)
            {
                //投入已大于产出
                if (inputNumRes.Data >= scheduleNum)
                {
                    return new ResponseComBool() { Success = false, Mesg = "该工单排程投入数量以达到计划数量" };
                }
                inputNumCur = inputNumRes.Data;
            }

            //进行入站
            ResponseComBool passStationRes = await TryPassStatoinAsync(request);
            if (passStationRes.Success == false) //进站失败
            {
                return passStationRes;
            }

            //进行载具绑定
            ResponseComBool bindVehicleRes = await TryBindVehicleAsync(request2);
            if (bindVehicleRes.Success == false) //绑定失败
            {
                return bindVehicleRes;
            }

            return bindVehicleRes;
        }
        //首站进站
        public async Task<ResponseComBool> PassFirstStationInAsync(PassStationRequest request, int inputNum, int scheduleNum)
        {
            //int inputNumCur;
            //var inputNumRes = await CheckOutputNumber(request, inputNum);

            ////记录工厂MES投入数量，返回结果异常时以产线记录为标准
            //if (inputNumRes.Success)
            //{
            //    //投入已大于产出
            //    if (inputNumRes.Data >= scheduleNum)
            //    {
            //        return new ResponseComBool() { Success = false, Mesg = "该工单排程投入数量以达到计划数量" };
            //    }
            //    inputNumCur = inputNumRes.Data;
            //}
            //进行入站
            ResponseComBool passStationRes = await TryPassStatoinAsync(request);

            var response = new ResponseBase(true, "");//(scheduleNum - inputNumRes.Data < 1)?await orderService.UpdateOrderAsync(request.data[0].lineCode):


            if (!response.Success) return new ResponseComBool() { Success = false, Mesg = response.Mesg };

            return passStationRes;
        }

        private async Task<ResponseComBase<int>> CheckOutputNumber(PassStationRequest request, int inputNum)
        {
            // 校验工序？
            // 查询投入数量
            ScheduleInPutNumberRequest request1 = new ScheduleInPutNumberRequest()
            {
                serviceId = "Product013_ScheduleInPutNumber",
                factoryCode = this.factoryCode,
                orderNumber = request.data[0].orderCode,
                scheduleNumber = request.data[0].scheduleCode
            };
            int inputNumCur = inputNum;
            ResponseComBase<int> inputNumRes = await TryScheduleInPutNumberAsync(request1);
            return inputNumRes;
        }


        //非首站进站
        public async Task<ResponseComBool> PassNonFirstStationInAsync(PassStationRequest request, SNInfo4PackageRequest request2, ProcessParametersRequest request3, BindVehicleRequest request4)
        {
            //查询SN基本信息
            ResponseComBase<SNInfo4PackageResponseSup> sNInfo4PackageRes = await TrySNInfo4PackageAsync(request2);
            if (sNInfo4PackageRes.Success == false) //无法查到工序信息
            {
                return new ResponseComBool { Success = false, Mesg = sNInfo4PackageRes.Mesg };
            }

            //查询工序参数
            ResponseComBool processParametersRes = await TryProcessParametersAsync(request3);
            //判断结果




            //进行入站
            ResponseComBool passStationRes = await TryPassStatoinAsync(request);
            if (passStationRes.Success == false) //进站失败
            {
                return passStationRes;
            }

            //进行载具绑定
            ResponseComBool bindVehicleRes = await TryBindVehicleAsync(request4);
            if (bindVehicleRes.Success == false) //绑定失败
            {
                return bindVehicleRes;
            }

            return bindVehicleRes;
        }

        public async Task<ResponseComBool> PassNonFirstStationInAsync(PassStationRequest request, SNInfo4PackageRequest request2, ProcessParametersRequest request3)
        {
            //查询SN基本信息
            //ResponseComBase<SNInfo4PackageResponseSup> sNInfo4PackageRes = await TrySNInfo4PackageAsync(request2);
            //if (sNInfo4PackageRes.Success == false) //无法查到工序信息
            //{
            //    return new ResponseComBool { Success = false, Mesg = sNInfo4PackageRes.Mesg };
            //}

            //查询工序参数
            //进行入站
            if (CanPass(request, request3).Result.Success)
            {
                ResponseComBool passStationRes = await TryPassStatoinAsync(request);
                return passStationRes;
            }
            return CanPass(request, request3).Result;
        }
        //出站
        public async Task<ResponseComBool> PassStationOutAsync(PassStationRequest request)
        {
            if (CanPass(request, null).Result.Success)
            {
                return await TryPassStatoinAsync(request); //工厂mes请求过站

            }
            else
            {
                return new ResponseComBool
                { Success = false,
                    Mesg = "未查询到" + request.data[0].snNumber + request.data[0].stationCode + "的进站记录" };
            }
        }




        //物料绑定信息  sn 产线 工位  //工单 排程
        public Dictionary<string, List<MaterialBindRecord>> BindingRelationship(string sn, string lineCode, string stationCode)
        {
            var res1 = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == sn &&
            x.LineCode == lineCode && x.StationCode == stationCode).ToList();

            Dictionary<string, List<MaterialBindRecord>> res2 = new();

            foreach (var material in res1)
            {
                string tmp = context.DC.Set<ProductBOM>().SingleOrDefault(x => x.OperationCode == stationCode && x.AssemblyMaterialCode == material.AssemblyMaterialCode)?.Field1;

                if (tmp != "" && tmp != null)
                {
                    if (res2.ContainsKey(tmp))
                    {
                        res2[tmp].Add(material);
                    }
                    else
                    {
                        res2.Add(tmp, new List<MaterialBindRecord>() { material });
                    }

                }
                else
                {
                    if (res2.ContainsKey(material.AssemblyMaterialCode))
                    {
                        res2[material.AssemblyMaterialCode].Add(material);
                    }
                    else
                    {
                        res2.Add(material.AssemblyMaterialCode, new List<MaterialBindRecord>() { material });
                    }
                }
            }
            return res2;
        }


        public ResponseComSN FindPassStationSN(string lineCode, string stationCode)
        {
            try
            {
                DateTime date1 = DateTime.Now;
                var res = context.DC.Set<PassStationRecord>().Where(e => e.LineCode == lineCode && e.StationCode == stationCode)
                    .OrderByDescending(e => e.ID).FirstOrDefault();
                DateTime date2 = DateTime.Now;
                if (res == null) return new ResponseComSN() { Success = false, SN = "托盘未进站,请等托盘就位" };

                if (res.ReqType == "1")
                {
                    return new ResponseComSN()
                    {
                        Success = true,
                        SN = res.SnNumber,
                        OrderCode = res.OrderCode,
                        ScheduleCode = res.ScheduleCode,
                        MaterialCode = res.MaterialCode,
                        MaterialName = res.MaterialName
                    };
                }
                else
                {
                    return new ResponseComSN() { Success = false, SN = "托盘未进站,请等托盘就位" };
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, ex.Message);
                return new ResponseComSN() { Success = false, SN = "获取工位SN信息失败" };
            }
        }


        //获取 工单排程 产线工位 对应的出站数量
        public ResponseComBase<int> GetPassStatonCount(string orderCode, string scheduleCode, string lineCode, string stationCode)
        {
            try
            {
                // 查询出站数量
                int res = context.DC.Set<PassStationRecord>().Where(e => e.OrderCode == orderCode && e.ScheduleCode == scheduleCode
                             && e.StationCode == stationCode && e.ReqType == "2").Count();
                return new ResponseComBase<int> { Success = true, Data = res, Mesg = "success" };

            }
            catch (Exception ex)
            {
                logger.LogError(ex, ex.Message);
                return new ResponseComBase<int>() { Success = false, Data = 0, Mesg = ex.Message };
            }
        }


        public async Task<FactoryAPIBase.ApiResponse> UploadMaterialBinding(PassStationCommunication.MaterialBindRequest materialBindRequest)
        {
            string url = "http://" + mesIP + ":" + mesPort + configuration["PDTemplate"];
            string psd = JsonConvert.SerializeObject(materialBindRequest);
            string value = await httpService.PostDataAsync(url, psd);
            ApiResponse response = JsonConvert.DeserializeObject<ApiResponse>(value);
            return response;
        }


        // 物料绑定1
        public MaterialBindRequestSup MapRecord2RequestSup(MaterialBindRecord record)
        {
            MaterialBindRequestSup request = new MaterialBindRequestSup();
            request.lineCode = record.LineCode;
            request.stationCode = record.StationCode;
            request.orderCode = record.OrderCode;
            request.scheduleCode = record.ScheduleCode;
            request.snNumber = record.SnNumber;
            request.assemblyMaterialCode = record.AssemblyMaterialCode;
            request.assemblyMaterialQty = record.AssemblyMaterialQty;
            request.assemblySort = record.AssemblySort;
            request.assemblyTime = DateTime.Parse(record.AssemblyTime);
            request.assemblyMaterialName = record.AssemblyMaterialName;
            request.assemblyMaterialVersion = record.AssemblyMaterialVersion;
            request.assemblyMaterialSn = record.AssemblyMaterialSn;
            request.materialBatchNo = record.MaterialBatchNo;
            return request;
        }


        // 物料绑定2
        public MaterialBindRecord MapProductBOMToMaterialBindRecord(string sn)
        {
            var bom = context.DC.Set<ProductBOM>().SingleOrDefault(x =>
                x.OrderCode == context.DC.Set<TrayBindVSN>().SingleOrDefault(y => y.VSN == sn).OrderCode);
            MaterialBindRecord record = new MaterialBindRecord();

            record.LineCode = bom?.Assemblyline;
            record.StationCode = "StationCode";
            record.OrderCode = bom?.OrderCode;
            record.ScheduleCode = bom?.ScheduleNumber;
            record.SnNumber = sn;
            record.AssemblyMaterialCode = bom.AssemblyMaterialCode;
            record.AssemblyMaterialQty = bom.AssemblyConsumption;
            record.AssemblySort = "AssemblySort";
            record.AssemblyTime = "AssemblyTime";
            record.AssemblyMaterialName = bom.AssemblyMaterialName;
            record.AssemblyMaterialVersion = bom.AssemblyMaterialVersion;
            record.AssemblyMaterialSn = "AssemblyMaterialSn";
            record.MaterialBatchNo = "MaterialBatchNo";
            record.Uploadflag = null;
            return record;
        }


        /// <summary>
        /// 校验物料是否装填完毕
        /// </summary>
        /// <param name="list1"></param>
        /// <param name="list2"></param>
        /// <returns></returns>
        private async Task<bool> JudgeMaterialIsFilled(List<MaterialBindRecord> list1, List<ProductBOM> list2)
        {
            foreach (var item in list2)
            {
                int count = list1.Where(e => e.AssemblyMaterialCode == item.AssemblyMaterialCode).Count();
                int number;
                int.TryParse(item.AssemblyConsumption, out number);
                if (count != number)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 校验物料在当前工位是否重复绑定
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        public async Task<bool> MaterialJudgeRepeat(MaterialBindRecord record)
        {
            int Count = context.DC.Set<MaterialBindRecord>().Where(x => x.StationCode == record.StationCode && x.AssemblyMaterialSn == record.AssemblyMaterialSn).Count();
            if (Count > 0)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 校验当前工位是否已经完成某个物料编码对应的物料信息的绑定
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        public async Task<ResponseBase> IsSingleMaterialFilled(MaterialBindRecord record,List<ProductBOM> boms)
        {
            //查找这个sn号里面是否有对应此物料编码和工单号下的物料绑定记录
            int Count = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == record.SnNumber && x.AssemblyMaterialCode == record.AssemblyMaterialCode
            && x.OrderCode == record.OrderCode&&x.StationCode==record.StationCode).Count();
            if (Count == 0)
                return new ResponseBase(true, "");
            else
            {
                var operation = ExstractOperation(record.StationCode);
                //查找需要绑定物料清单
                var bom = boms.Where(e => e.OrderCode == record.OrderCode && e.ScheduleNumber == record.ScheduleCode
                                 && e.OperationCode == operation).FirstOrDefault();
                int number;
                int.TryParse(bom.AssemblyConsumption, out number);
                if (Count < number)
                    return new ResponseBase(true, "");
                else
                    return new ResponseBase(false, "SN号" + record.SnNumber + "绑定物料已达量，无需再绑定物料" + record.AssemblyMaterialSn);
            }

        }

        // 校验 SN对应的物料绑定是否完成
        public async Task<bool> MaterialVerification(string snNumber, string lineCode, string operationCode, string stationCode, string orderCode, string scheduleCode, bool isVerification = true)
        {
            try
            {
                //获取已绑定物料清单
                var bindingLists = context.DC.Set<MaterialBindRecord>().Where(x => x.OrderCode == orderCode && x.ScheduleCode == scheduleCode
                                    && x.SnNumber == snNumber && x.StationCode == stationCode).ToList();

                if (isVerification)
                {
                    //查找需要绑定物料清单
                    var requiredLists = context.DC.Set<ProductBOM>().Where(e => e.OrderCode == orderCode && e.ScheduleNumber == scheduleCode
                                     && e.OperationCode == operationCode).ToList();
                    //如果不存在物料bom，直接返回true
                    if (requiredLists.Count == 0)
                    {
                        return true;
                    }
                    //合格则掉用工厂MES进行信息传递，不合格返回错误信息
                    bool res =await JudgeMaterialIsFilled(bindingLists, requiredLists);
                    if (res == false)
                    {
                        return false;
                    }
                }

                return true;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public string ExstractOperation(string stationCode)
        {
            int firstDashIndex = stationCode.IndexOf('-');
            if (firstDashIndex == -1)
                return stationCode;
            int secondDashIndex = stationCode.IndexOf("-", firstDashIndex + 1);
            if (secondDashIndex == -1) return stationCode;
            else return stationCode.Substring(0, secondDashIndex);
        }

        // 根据sn 绑定要求表生成 绑定记录
        public async Task<ResponseComBase<MaterialBindRecord>> CreateBindingRecord(string sn, List<ProductBOM> boms, PassStationRecord passRecord)
        {

            foreach (var item in boms)
            {
                if (Regex.IsMatch(sn, item.AssemblyMaterialRegex))
                {
                    //2-OP3180-0会直接传入前箱SN号需要校验是否是前箱SN
                    if (passRecord.StationCode == "2-OP3180-0")
                    {
                        var JudgeResult = await JudgeIsQXSN(sn);
                        if(!JudgeResult.Success)
                        {
                            await stationlogadd3(passRecord.LineCode, passRecord.StationCode, sn, "bad", JudgeResult.Mesg);
                            return new ResponseComBase<MaterialBindRecord>() { Success = false, Mesg = JudgeResult.Mesg };
                        }
                    }

                    MaterialBindRecord bindingRecord = new MaterialBindRecord()
                    {
                        LineCode = passRecord.LineCode,
                        StationCode = passRecord.StationCode,
                        OrderCode = passRecord.OrderCode,
                        ScheduleCode = passRecord.ScheduleCode,
                        SnNumber = passRecord.SnNumber,//SN码
                        AssemblyMaterialCode = item.AssemblyMaterialCode,//组件物料编码
                        AssemblyMaterialQty = "1",
                        //AssemblySort 
                        AssemblyTime = DateTime.Now.ToString("yyyy-MM-dd HH: mm:ss"),
                        AssemblyMaterialName = item.AssemblyMaterialName,//组件物料名称
                        AssemblyMaterialVersion = item.AssemblyMaterialVersion,
                        AssemblyMaterialSn = sn, //绑定物料sn
                        //MaterialBatchNo
                        Uploadflag = false,
                    };
                    return new ResponseComBase<MaterialBindRecord>() { Success = true, Data = bindingRecord };
                }


            }


            // 查找装配体虚拟Sn
            var responseSn = FindVirtualSn(sn);
            if (responseSn.Success == false)
            {
                return new ResponseComBase<MaterialBindRecord>() { Success = false, Mesg = responseSn.mesg };
            }

            foreach (var item in boms)
            {
                if (Regex.IsMatch(responseSn.Sn, item.AssemblyMaterialRegex))
                {
                    MaterialBindRecord bindingRecord = new MaterialBindRecord()
                    {
                        LineCode = passRecord.LineCode,
                        StationCode = passRecord.StationCode,
                        OrderCode = passRecord.OrderCode,
                        ScheduleCode = passRecord.ScheduleCode,
                        SnNumber = passRecord.SnNumber,
                        AssemblyMaterialCode = item.AssemblyMaterialCode,
                        AssemblyMaterialQty = "1",
                        //AssemblySort 
                        AssemblyTime = DateTime.Now.ToString("yyyy-MM-dd HH: mm:ss"),
                        AssemblyMaterialName = item.AssemblyMaterialName,
                        AssemblyMaterialVersion = item.AssemblyMaterialVersion,
                        AssemblyMaterialSn = responseSn.Sn, //绑定物料sn
                        //MaterialBatchNo
                        Uploadflag = false,
                    };
                    return new ResponseComBase<MaterialBindRecord>() { Success = true, Data = bindingRecord };
                }
            }

            // 无法找到对应需求的绑定物料
            return new ResponseComBase<MaterialBindRecord>() { Success = false, Mesg = "工位" + passRecord.StationCode + ": " + passRecord.SnNumber + "与" + sn + "无绑定需求" };
        }

        public async Task<ResponseBase> JudgeIsQXSN(string SN)
        {
            try
            {
                int Count = context.DC.Set<TrayBindVSN>().Where(x=>x.TrayStation=="2-OP3020-0"&&x.VSN==SN).Count();
                if (Count == 0)
                    return new ResponseBase(false, $"未查询到SN{SN}的上线绑定记录");
                return new ResponseBase(true, "");

            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"校验前箱虚拟物料异常：SN[{SN}],{ex.Message}");
            }
        }


        // 寻找sn对应装配体的主虚拟Sn
        public ResponseSn FindVirtualSn(string sn)
        {
            var res = this.context.DC.Set<MaterialBindRecord>().OrderByDescending(e => e.ID).FirstOrDefault(e => e.AssemblyMaterialSn == sn);
            if (res == null)
            {
                return new ResponseSn() { Success = false, mesg = "不符合本工位物料条码规则或此物料未进行过与虚拟sn的绑定" };
            }
            else
            {
                // 通过工单查找物料编码
                var orderInfo = this.context.DC.Set<Order_Model>().SingleOrDefault(e => e.OrderCode == res.OrderCode && e.ScheduleCode == res.ScheduleCode);
                if (orderInfo == null)
                {
                    return new ResponseSn() { Success = false, mesg = "工单信息缺失" };
                }
                else
                {
                    return new ResponseSn() { Success = true, Sn = res.SnNumber, MaterialCode = orderInfo.MaterialCode };
                }
            }
        }

        public async Task<Order_Model> FindOrderInfo(string sn)
        {
            var vsnbindtrayRecord = context.DC.Set<TrayBindVSN>().Where(x => x.VSN == sn).FirstOrDefault();
            return context.DC.Set<Order_Model>().Where(x => x.OrderCode == vsnbindtrayRecord.OrderCode).FirstOrDefault();
        }

        public async Task<string> FindLastOP2StationCode(string orderCode)
        {
            try
            {
                var operation = context.DC.Set<RouteOperation>().Where(x => x.OrderCode == orderCode && (x.NextOperationCode == null || x.NextOperationCode == "")).FirstOrDefault();
                if (operation != null)
                    return operation.OperationCode + "-0";
                else return "";
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public async Task<ResponseBase> PostAddtionalPassStationRecord(Postpara para)
        {
            PassStationRequestSup passStationRequestSup = new PassStationRequestSup();
            PassStationRequest passStationRequest = new PassStationRequest();

            passStationRequestSup.snNumber = para.sn;
            var trayinfo = context.DC.Set<TrayBindVSN>().Where(x => x.VSN == para.sn).SingleOrDefault();
            if (trayinfo == null)
                return new ResponseBase(false, "sn不存在上线绑定记录");

            passStationRequestSup.TrayNumber = trayinfo.TrayCode;
            passStationRequestSup.orderCode = para.orderinfo.OrderCode;
            passStationRequestSup.scheduleCode = para.orderinfo.ScheduleCode;
            passStationRequestSup.materialCode = para.orderinfo.MaterialCode;
            passStationRequestSup.materialName = para.orderinfo.MaterialName;
            passStationRequestSup.materialVersion = para.orderinfo.MaterialVersion;
            passStationRequestSup.lineCode = para.orderinfo.Field5; //工厂产线编码
            passStationRequestSup.stationCode = para.stationCode;
            passStationRequestSup.operationCode = ExstractOperation(para.stationCode);

            passStationRequestSup.passStatus = "pass";
            passStationRequestSup.reqType = "2";
            passStationRequestSup.isProduct = 0;
            passStationRequestSup.passBeginTime = "";
            passStationRequestSup.passEndTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();

            passStationRequest.data = new List<PassStationRequestSup> { passStationRequestSup };
            //passStationRequest.data.Add(passStationRequestSup);
            passStationRequest.serviceId = "Product003_PassStation";
            passStationRequest.userId = "";
            passStationRequest.userName = "";
            passStationRequest.snBindState = "1";
            passStationRequest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            passStationRequest.factoryCode = "TH13";
            passStationRequest.timer = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            ResponseComBool response = await TryPassStatoinAsync(passStationRequest);
            if (response.Success == true)
            {
                return new ResponseBase(true, "补漏产出成功");
            }
            //Results<Ok<ResponseBase>, BadRequest<string>> results = await normalPassStationDomain.PassOutStation(passStationRequestSup, para.orderinfo);
            //await normalPassStationDomain.AddPassStationlog(results, passStationRequestSup, "出站", para.orderinfo.LineCode);
            ////载具绑定
            //await normalPassStationDomain.RequestBindVehicle(passStationRequestSup, passStationRequestSup.TrayNumber, para.orderinfo);
            //if (results.Result is Ok<ResponseBase> okObjectResult)
            //{
            //    ResponseBase res = okObjectResult.Value as ResponseBase;
            //    if (res.Success == true)
            //    {
            //        return new ResponseBase(true, "补漏产出成功");
            //    }
            //    return new ResponseBase(false, "补漏产出失败");
            //}
            return new ResponseBase(false, "补漏产出失败" + response.Mesg);
        }

        public async Task<Results<Ok<ResponseBase>, BadRequest<string>>> AddLMESPassStationRecord(PassStationRequestSup passStationRequestSup, Order_Model order,
            ResponseComBool response)
        {
            PassStationRecord record = new PassStationRecord();
            if (response.Success == false)
            {

                //return TypedResults.Ok(new ResponseBase(false, response.Mesg));
                record.Uploadflag = false;
            }
            else
            {
                record.Uploadflag = true;
            }

            record.LineCode = order.LineCode;
            record.MaterialCode = order.MaterialCode;
            record.MaterialName = order.MaterialName;
            record.MaterialVersion = order.MaterialVersion;
            record.OperationCode = passStationRequestSup.operationCode;
            record.OrderCode = order.OrderCode;
            //record.PassBeginTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            //record.PassEndTime = "";
            record.PassStatus = passStationRequestSup.passStatus;
            record.ScheduleCode = order.ScheduleCode;
            record.SnNumber = passStationRequestSup.snNumber;
            record.StationCode = passStationRequestSup.stationCode;
            record.ShipCode = passStationRequestSup.shipCode;
            record.MachineCode = context.DC.Set<Machine>()
                .SingleOrDefault(x => x.StationCodeId == passStationRequestSup.stationCode)?.MachineCode;
            // singleordefault异常 待修改
            //record.IsProduct = record.StationCode == _context.DC.Set<Route>()
            //    .SingleOrDefault(x => x.ProductCode == order.MaterialCode)?.Field4 && passStationRequestSup.reqType == "2"
            //    ? "1"
            //    : "0";
            record.IsProduct = passStationRequestSup.isProduct.ToString();
            record.ReqType = passStationRequestSup.reqType;
            record.UserId = "";
            record.UserName = "";
            //record.Uploadflag = false;

            if (record.ReqType == "1")
            {
                record.PassBeginTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            }
            else
            {
                record.PassEndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            }

            context.DC.Set<PassStationRecord>().Add(record);
            await context.DC.SaveChangesAsync();
            return TypedResults.Ok(new ResponseBase(true, record.SnNumber));
        }

        public record ResponseSn {
            public string Sn { get; set; }
            public bool Success { get; set; }
            public string MaterialCode { get; set; }
            public string mesg { get; set; }
        }
        // 本地添加绑定记录
        public async Task<ResponseComBool> AddLocalBindingRecord(MaterialBindRecord record, bool upLoadFlag)
        {
            try
            {
                record.Uploadflag = upLoadFlag;
                record.CreateTime = DateTime.Now;
                context.DC.Set<MaterialBindRecord>().Add(record);
                //context.DC.SaveChangesAsync();
                await context.DC.SaveChangesAsync();

                return new ResponseComBool() { Success = true };
            }
            catch (Exception ex)
            {
                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }

        }
        public async Task<ResponseComBool> AddBindingRecord(List<MaterialBindRecord> records, StationLogRecord stationLog)
        {
            try
            {
                foreach (var record in records)
                {
                    string operationCode = ExstractOperation(record.StationCode);
                    //var res = BindingVerification(record.SnNumber, record.AssemblyMaterialSn, record.LineCode, operationCode, record.StationCode, record.OrderCode, record.ScheduleCode, record.AssemblyMaterialCode);
                    //if (res.Success == true)
                    //{
                    //    stationLog.LogType = "good";
                    //    stationLog.Log = record.AssemblyMaterialSn + "绑定" + record.SnNumber + "数据本地保存成功，" + res.Mesg;
                    //    context.DC.Set<StationLogRecord>().Add(stationLog);
                    //    await context.DC.SaveChangesAsync();

                    //}
                    //else
                    //{
                    //    stationLog.LogType = "bad";
                    //    stationLog.Log = record.AssemblyMaterialSn + "绑定" + record.SnNumber + "数据本地保存失败，" + res.Mesg;
                    //    context.DC.Set<StationLogRecord>().Add(stationLog);
                    //    await context.DC.SaveChangesAsync();
                    //    return res;
                    //}
                    record.CreateTime = DateTime.Now;
                    context.DC.Set<MaterialBindRecord>().Add(record);
                }
                await context.DC.SaveChangesAsync();
                return new ResponseComBool() { Success = true };
            }
            catch (Exception ex)
            {
                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }
        }


        public async Task<ResponseComBool> CanPass(PassStationRequest request, ProcessParametersRequest request3)
        {
            if (request.data[0].reqType == "1")
            {
                var a = context.DC.Set<RouteOperation>().SingleOrDefault(x =>
                    x.OperationCode == request3.operationCode &&
                    x.OrderCode == request.data[0].orderCode);
                if (a == null)
                    return new ResponseComBool()
                    { Success = false, Mesg = "此托盘绑定工单的工艺路线没有此工位" };
                else
                {
                    try
                    {
                        var b = context.DC.Set<PassStationRecord>().SingleOrDefault(x =>
                         x.OperationCode == a.LastOperationCode && x.SnNumber == request.data[0].snNumber && x.ReqType == "2");
                        if (b != null)
                            return new ResponseComBool()
                            {
                                //开启前后站校验线控时此success置为false
                                Success = true,
                                Mesg = "上一站未完成出站"
                            };
                    }
                    catch (Exception ex)
                    {
                        return new ResponseComBool()
                        {
                            Success = false,
                            Mesg = request.data[0].snNumber + "在" + a.LastOperationCode + "多次出站"
                        };
                    }

                }


                //var processParametersRes = await TryProcessParametersAsync(request3);

                //if (processParametersRes.Success == false) return processParametersRes;
                //else if (processParametersRes.Mesg == "N") processParametersRes.Success = false;
                //else
                //{
                //    request3.operationCode = a.LastOperationCode;
                //    return await CanPass(request, request3);
                //}
                //return processParametersRes;

                return new ResponseComBool()
                {
                    Success = true,
                    Mesg = "暂不做过站校验"
                };
            }
            else if (request.data[0].reqType == "2")
            {
                var b = context.DC.Set<PassStationRecord>().Where(x =>
                    x.OperationCode == request.data[0].operationCode
                    && x.SnNumber == request.data[0].snNumber && x.ReqType == "1"
                    && x.StationCode == request.data[0].stationCode).ToList();
                if (b.Count != 0)
                    return new ResponseComBool()
                    {
                        Success = true,
                        Mesg = ""
                    };
                return new ResponseComBool()
                {
                    Success = false,
                    Mesg = "The passin record is not found ,please check the record"
                };
            }
            return new ResponseComBool()
            {
                Success = false,
                Mesg = "request is not valid"
            };
        }
        public async Task<ResponseComBool> CanPass1(PassStationRequest request, ProcessParametersRequest request3)
        {
            // 检查请求类型
            switch (request.data[0].reqType)
            {
                case "1":
                    return await HandlePassinRequest(request, request3);
                case "2":
                    return HandlePassoutRequest(request);
                default:
                    return new ResponseComBool
                    {
                        Success = false,
                        Mesg = "Request type is not valid"
                    };
            }
        }

        private async Task<ResponseComBool> HandlePassinRequest(PassStationRequest request, ProcessParametersRequest request3)
        {
            var a = context.DC.Set<RouteOperation>().SingleOrDefault(x =>
                x.OperationCode == request3.operationCode &&
                x.OrderCode == request.data[0].orderCode);

            if (a == null)
                return new ResponseComBool
                {
                    Success = false,
                    Mesg = "The route operation is not found, please sync the route data"
                };

            var b = context.DC.Set<PassStationRecord>().SingleOrDefault(x =>
                x.OperationCode == a.LastOperationCode &&
                x.SnNumber == request.data[0].snNumber &&
                x.ReqType == "2");

            if (b != null)
                return new ResponseComBool
                {
                    Success = true,
                    Mesg = "The pass station record is valid"
                };

            var processParametersRes = await TryProcessParametersAsync(request3);

            if (!processParametersRes.Success)
                return processParametersRes;

            if (processParametersRes.Mesg == "N")
                return new ResponseComBool
                {
                    Success = false,
                    Mesg = "Process parameters are not valid"
                };

            request3.operationCode = a.LastOperationCode;
            return await CanPass(request, request3); // 递归调用
        }

        private ResponseComBool HandlePassoutRequest(PassStationRequest request)
        {
            var b = context.DC.Set<PassStationRecord>().SingleOrDefault(x =>
                x.OperationCode == request.data[0].operationCode &&
                x.SnNumber == request.data[0].snNumber &&
                x.ReqType == "1" &&
                x.StationCode == request.data[0].stationCode);

            if (b != null)
                return new ResponseComBool
                {
                    Success = true,
                    Mesg = "The pass station record is valid"
                };

            return new ResponseComBool
            {
                Success = false,
                Mesg = "The pass station record is not found, please check the record"
            };
        }        // 本地插入物料绑定校验
        public ResponseComBool BindingVerification(string snNumber, string bindingSN, string lineCode, string operationCode, string stationCode, string orderCode, string scheduleCode, string materialCode)
        {
            try
            {
                // 判断 bindingSN是否重复绑定
                var isRepeatBinding = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == snNumber && x.AssemblyMaterialSn == bindingSN).ToList().Count;
                if (isRepeatBinding > 0)
                {
                    return new ResponseComBool() { Success = false, Mesg = bindingSN + "物料编码: " + materialCode + "已经完成绑定，请检查" };

                }

                // 获取需求的数量
                var requiredList = context.DC.Set<ProductBOM>().Where(e => e.OrderCode == orderCode && e.ScheduleNumber == scheduleCode
                                    && e.Assemblyline == lineCode && e.OperationCode == operationCode && e.AssemblyMaterialCode == materialCode).ToList();
                int count = 0;
                foreach (var item in requiredList)
                {
                    count += int.Parse(item.AssemblyConsumption);
                }

                // 获取已绑定数量
                var hasBindingCount = context.DC.Set<MaterialBindRecord>().Where(x => x.OrderCode == orderCode && x.ScheduleCode == scheduleCode
                                    && x.LineCode == lineCode && x.StationCode == stationCode && x.SnNumber == snNumber && x.AssemblyMaterialCode == materialCode).ToList().Count;
                if (hasBindingCount < count)
                {
                    return new ResponseComBool() { Success = true };
                }
                else
                {
                    return new ResponseComBool() { Success = false, Mesg = bindingSN + "物料编码: " + materialCode + "已满足装配需求，请检查" };
                }
            }
            catch (Exception ex)
            {

                return new ResponseComBool() { Success = false, Mesg = ex.Message };
            }

        }

        public List<StationLogRecord> GetStationLogs(string lineCode, string stationCode)
        {
            List<StationLogRecord> records = new List<StationLogRecord>();
            try
            {
                records = context.DC.Set<StationLogRecord>().Where(e => e.StationCode == stationCode).OrderByDescending(e => e.CreateTime).Take(15).ToList();
                return records;
            }
            catch (Exception)
            {
                records.Add(new StationLogRecord() { CreateTime = DateTime.Now, Log = "获取日志信息异常" });
                return records;
            }
        }

        public List<BatchComplitionResponse.BatchFlushUI> GetBatchFlushUIs(string lineCode,string stationCode)
        {
            List<BatchComplitionResponse.BatchFlushUI> batchFlushUIs = new List<BatchComplitionResponse.BatchFlushUI>();
            try
            {
                var batchComplitions = context.DC.Set<BatchCompilations>().Where(x => x.stationCode == stationCode && x.isUse == true).ToList();
                foreach(var batchComplition in batchComplitions)
                {
                    BatchComplitionResponse.BatchFlushUI info = new BatchComplitionResponse.BatchFlushUI();
                    info.materialCode = batchComplition.materialCode;
                    info.materialName = batchComplition.materialName;
                    info.batchCode = batchComplition.batchCode;
                    info.batchSingleCostQty = batchComplition.batchSingleCostQty;
                    info.batchAddQty = batchComplition.batchAddQty;
                    info.batchMarginQty = batchComplition.batchMarginQty;
                    info.suplierID = batchComplition.Filed1;
                    info.isUse = batchComplition.isUse;
                    info.UpdateTime = batchComplition.UpdateTime;
                    batchFlushUIs.Add(info);
                }
                return batchFlushUIs;
            }
            catch (Exception ex)
            {
                return batchFlushUIs;
            }

        }


        // 获取sn的 产线、工位 入站信息
        public async Task<PassStationRecord> FindInStationInfoAsync(string sn, string lineCode, string stationCode)
        {
            try
            {
                var res = await context.DC.Set<PassStationRecord>().SingleOrDefaultAsync(e => e.SnNumber == sn && e.StationCode == stationCode && e.ReqType == "1");
                return res;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> uploadMaterialBatch(UploadMaterial.uploadmaterialrequest request)
        {
            try
            {
                string psd = JsonConvert.SerializeObject(request);
                string value = await httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/product/Product_Information", psd);
                UploadMaterial.uploadmaterialresponse response = JsonConvert.DeserializeObject<UploadMaterial.uploadmaterialresponse>(value);
                if (response.data.code == "000000")
                {
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Product006_ProductParameters生产数据上传接口上传生产数据
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ResponseBase> PostProductPara006(ProductDataRequest request)
        {
            Producepara.Produce006Request producepara = new Producepara.Produce006Request();
            producepara.data = new List<Producepara.DataElement>();

            Producepara.DataElement data = new Producepara.DataElement();
            data.dataList = new List<Producepara.DataListElement>();



            double num;
            string stationCode = string.Empty;
            string materialCode = string.Empty;
            string materialVersion = string.Empty;
            string snNumber = string.Empty;
            foreach (var item in request.data)
            {
                Producepara.DataListElement dataList = new Producepara.DataListElement();
                //if (double.TryParse(item.paramRange1, out num))
                //    dataList.paramRange1 = num;
                //else dataList.paramRange2 = 0;
                //if (double.TryParse(item.paramRange2, out num))
                //    dataList.paramRange1 = num;
                //else dataList.paramRange2 = 0;
                stationCode = item.stationCode;
                materialCode = item.materialCode;
                materialVersion = item.materialVersion;
                snNumber = item.snNumber;

                dataList.paramCode = item.paramCode;
                dataList.paramName = item.paramName;
                dataList.checkResult = 0;
                dataList.paramTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                dataList.realValue = item.realValue;
                data.dataList.Add(dataList);

            }
            data.lineCode = _LineCode;
            data.machineCode = stationCode;
            data.materialCode = materialCode;
            data.materialVersion = materialVersion;
            data.snNumber = snNumber;
            data.stationCode = stationCode;

            producepara.data.Add(data);
            try
            {
                string postdata = JsonConvert.SerializeObject(producepara);
                string value = await httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/base/Base_Information", postdata);
                responseMes response = JsonConvert.DeserializeObject<responseMes>(value);
                if (response.code == "000000")
                {
                    return new ResponseBase(true, response.mesg);
                }
                else
                    return new ResponseBase(false, "工厂mes返回失败，Product006_ProductParameters,接口上传生产产生失败，" + response.mesg);
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, "Product006_ProductParameters上传异常" + ex.Message);
            }
        }

        public async Task<bool> GetPrintStyle()
        {
            var printstyle = context.DC.Set<PrintStyle>().Where(x => x.Name == "11").ToList();
            if (printstyle == null)
                return false;
            MapToPrintStyle.PrintConfiguration printPanel = JsonConvert.DeserializeObject<MapToPrintStyle.PrintConfiguration>(printstyle[0].Style);

            int i = 0;

            return true;
        }

        /// <summary>
        /// 通过组件sn在工厂mes中反查sn号
        /// </summary>
        /// <param name="Assemblysn"></param>
        /// <returns></returns>
        public async Task<ResponseBase> AssemblySnPeggingSn(string Assemblysn)
        {
            try
            {
                PeggingRequest request = new PeggingRequest("AssemblyNumber_SearchSn", "TH13", Assemblysn);
                string psd = JsonConvert.SerializeObject(request);
                string value = await httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/base/Base_Information", psd);
                try
                {
                    PeggingReponse response = JsonConvert.DeserializeObject<PeggingReponse>(value);
                    if (response.code == "000000")
                    {
                        return new ResponseBase(true, response.data.snNumber);
                    }
                    return new ResponseBase(false, "反查无sn信息" + response.mesg);
                }
                catch (Exception ex)
                {
                    ReponseBasic response = JsonConvert.DeserializeObject<ReponseBasic>(value);
                    return new ResponseBase(false, "反查无sn信息");
                }



            }
            catch (Exception ex)
            {
                return new ResponseBase(false, "反查sn失败" + ex.Message);
            }
        }

        public async Task<ResponseBase> PersonVerify(PersonVerifyRequest verifyRequest)
        {
            try
            {

            }
            catch (Exception ex)
            {

            }
            return new ResponseBase(false, "反查sn失败");
        }

        public async Task<string> Totest(string data)
        {
            string value = await httpService.PostDataAsync("http://10.89.56.96:8088/api/base/Base_Information", data);
            return value;
        }


        /// <summary>
        /// 批次缺料报警
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> PostBatchAlarm(BatchInforRequest.BatchScadaRequest request)
        {
            try
            {
                AlarmRequest.WarningData warnresquest = new AlarmRequest.WarningData();
                warnresquest.data = new List<AlarmRequest.WarningDetail>();
                warnresquest.factoryCode = factoryCode;
                warnresquest.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                AlarmRequest.WarningDetail detail = new AlarmRequest.WarningDetail();
                detail.lineCode = request.LineCode;
                detail.stationCode = request.OperationCode;
                detail.operationCode = ExstractOperation(request.OperationCode);
                detail.warningCode = "YC001";
                detail.warningType = "1";
                detail.warningDesc = "批次" + request.BatchCode + "即将用完，请上料";
                detail.warningTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                string psd = JsonConvert.SerializeObject(warnresquest);
                string value = await httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/base/Base_Information", psd);

                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// 全检UI界面过站信息
        /// </summary>
        /// <param name="SN"></param>
        /// <returns></returns>
        public async Task<List<UIResponse.FinishPassRecord>> FinishPassRecords(string SN)
        {
            var CSmaterialSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == SN).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
            var PadSelectStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "PadSelectStation").First().propertyValue;
            var QXSN = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber==SN && x.StationCode == PadSelectStation).FirstOrDefault()?.AssemblyMaterialSn;
            var passrecords = context.DC.Set<PassStationRecord>().Where(x => (x.SnNumber == SN||x.SnNumber==CSmaterialSN||x.SnNumber==QXSN) && x.PassStatus == "pass").OrderBy(x=>x.OperationCode).ToList();


            List<UIResponse.FinishPassRecord> records = new List<UIResponse.FinishPassRecord>();
            try
            {
                foreach (var passrecord in passrecords)
                {
                    UIResponse.FinishPassRecord data = new UIResponse.FinishPassRecord();
                    data.id = passrecord.OperationCode;
                    var op = context.DC.Set<RouteOperation>().Where(x => x.OperationCode == passrecord.OperationCode && x.OrderCode == passrecord.OrderCode).FirstOrDefault();
                    if (op == null)
                        continue;
                    data.name = op.OperationName;
                    data.status = "OK";
                    records.Add(data);
                }
                return records;

            }
            catch (Exception ex)
            {
                return new List<UIResponse.FinishPassRecord>();
            }
        }

        /// <summary>
        /// 全检UI界面物料绑定数据
        /// </summary>
        /// <param name="SN"></param>
        /// <returns></returns>
        public async Task<List<UIResponse.MaterialRecord>> UIMaterialRecords(string SN)
        {
            List<UIResponse.MaterialRecord> records = new List<UIResponse.MaterialRecord>();
            //测试线信息也要加上
            var CSmaterialSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == SN).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
            //前箱也要
            var PadSelectStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "PadSelectStation").First().propertyValue;
            var QXSN = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == SN && x.StationCode == PadSelectStation).FirstOrDefault()?.AssemblyMaterialSn;

            var materialrecords = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == SN||x.SnNumber==CSmaterialSN||x.SnNumber==QXSN).ToList();
            try
            {
                foreach (var record in materialrecords)
                {


                    UIResponse.MaterialRecord materialRecord = new UIResponse.MaterialRecord();
                    materialRecord.stationId = record.StationCode;
                    materialRecord.materialCode = record.AssemblyMaterialCode;
                    materialRecord.materialName = record.AssemblyMaterialName;
                    materialRecord.materialSN = record.AssemblyMaterialSn;
                    records.Add(materialRecord);

                }
                return records;
            }
            catch (Exception ex)
            {
                return new List<UIResponse.MaterialRecord>();
            }
        }

        /// <summary>
        /// 全检UI界面生产参数
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public async Task<List<UIResponse.ProcessDataRecord>> UIProcessDataRecords(string SN) //UIRequest.PassRecordUI res
        {
            List<UIResponse.ProcessDataRecord> processDatas = new List<UIResponse.ProcessDataRecord>();
            try
            {
                var CSmaterialSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == SN).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
                var PadSelectStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "PadSelectStation").First().propertyValue;
                var QXSN = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == SN && x.StationCode == PadSelectStation).FirstOrDefault()?.AssemblyMaterialSn;
                List<ProduceDataRecord> processes = new List<ProduceDataRecord>();
                List<TighteningData> tightenings = new List<TighteningData>();
                if (CSmaterialSN != null && CSmaterialSN != "")
                {
                    processes.AddRange(context.DC.Set<ProduceDataRecord>().Where(x => x.SN == SN || x.SN == CSmaterialSN).ToList());
                    tightenings.AddRange( context.DC.Set<TighteningData>().Where(x => x.sn == SN || x.sn == CSmaterialSN).ToList());
                }
                else
                {
                    processes.AddRange(context.DC.Set<ProduceDataRecord>().Where(x => x.SN == SN ).ToList());
                    tightenings.AddRange(context.DC.Set<TighteningData>().Where(x => x.sn == SN ).ToList());

                }
                if(QXSN != null && QXSN != "")
                {
                    processes.AddRange(context.DC.Set<ProduceDataRecord>().Where(x => x.SN == QXSN).ToList());
                    tightenings.AddRange(context.DC.Set<TighteningData>().Where(x => x.sn == QXSN).ToList());
                }

                //常规生产数据
                foreach (var record in processes)
                {

                    string opCode = ExstractOperation(record.StationCode);
                    var op = context.DC.Set<RouteOperation>().Where(x => x.OperationCode == opCode).FirstOrDefault();
                    if (op == null)
                        continue;

                    char[] delimiterChars = { '*' };
                    string[] dataname = record.DataName.Split(delimiterChars);
                    string[] data = record.Data.Split(delimiterChars);
                    try
                    {
                        for (int i = 0; i < dataname.Length; i++)
                        {
                            UIResponse.ProcessDataRecord dataRecord = new UIResponse.ProcessDataRecord();
                            dataRecord.processId = record.StationCode;
                            dataRecord.processName = op.OperationName;
                            dataRecord.paramName = dataname[i];
                            dataRecord.value = data[i];
                            processDatas.Add(dataRecord);
                        }
                    }
                   catch(Exception ex)
                    {
                        continue;
                    }

                }


                //拧紧生产数据
                foreach (var tighten in tightenings) 
                {
                    var stationName =  context.DC.Set<Station>().Where(x => x.StationCode == tighten.project_name).FirstOrDefault().StationName;
                    if(stationName == null) 
                        stationName=tighten.project_name;
                    else
                        stationName = stationName.Trim();
                    UIResponse.ProcessDataRecord tightendata= new UIResponse.ProcessDataRecord();
                    tightendata.processId = tighten.project_name;
                    tightendata.processName = stationName;
                    tightendata.paramName = "拧紧ID"+tighten.screw_id.ToString()+"的扭矩";
                    tightendata.value = tighten.torque;

                    processDatas.Add(tightendata);
                    UIResponse.ProcessDataRecord tightendata2 = new UIResponse.ProcessDataRecord();
                    tightendata2.processId = tighten.project_name;
                    tightendata2.processName = stationName;
                    tightendata2.paramName = "拧紧ID" + tighten.screw_id.ToString() + "的角度";
                    tightendata2.value = tighten.angle;

                    processDatas.Add(tightendata2);
                }

                return processDatas;
            }
            catch (Exception ex)
            {
                return new List<ProcessDataRecord> { };
            }
        }

        public async Task<List<UIResponse.ProcessDataRecord>> UIZXProcessDataRecords(List<UIResponse.MaterialRecord> materialRecords)
        {
            List<UIResponse.ProcessDataRecord> processDataRecords = new List<UIResponse.ProcessDataRecord>();
            try
            {
                foreach (var materialRecord in materialRecords)
                {
                    var materialPD = context.DC.Set<MaterialPD>().Where(x=>x.CurrentSN==materialRecord.materialSN).ToList();

                }
                return processDataRecords;
            }
            catch (Exception ex)
            {
                return processDataRecords;
            }

        }

        /// <summary>
        /// 追溯界面的批次信息展示
        /// </summary>
        /// <param name="materialRecords"></param>
        /// <returns></returns>
        public async Task<List<UIResponse.BatcInfo>> UIBatchRecords(List<UIResponse.MaterialRecord> materialRecords)
        {
            List <UIResponse.BatcInfo> batcInfos = new List<UIResponse.BatcInfo>();
            try
            {
                foreach (var record in materialRecords)
                {
                    var batchinfo = context.DC.Set<BatchInfor>().Where(x=>x.CurrentSN==record.materialSN).ToList();
                    foreach(var batch in batchinfo)
                    {
                        UIResponse.BatcInfo info = new UIResponse.BatcInfo();
                        info.batchNumber = batch.BatchCode;
                        info.station = batch.OperationCode;
                        info.materialName = batch.OperationName;
                        info.consumption = batch.SingleConsumption;
                        batcInfos.Add(info);
                    }
                }
                return batcInfos;
            }
            catch 
            {
                return batcInfos;
            }
        }


        public async Task<List<UIResponse.BatcInfo>> CSBatchRecords(string TZSN)
        {
            List<UIResponse.BatcInfo> batcInfos = new List<UIResponse.BatcInfo>();
            try
            {
                var CSmaterialSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == TZSN).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
                if(CSmaterialSN == null)
                    return batcInfos;
                var batchinfo = context.DC.Set<BatchInfor>().Where(x => x.CurrentSN == CSmaterialSN).ToList();
                foreach (var batch in batchinfo)
                {
                    UIResponse.BatcInfo info = new UIResponse.BatcInfo();
                    info.batchNumber = batch.BatchCode;
                    info.station = batch.OperationCode;
                    info.materialName = batch.OperationName;
                    info.consumption = batch.SingleConsumption;
                    batcInfos.Add(info);
                }
                return batcInfos;
            }
            catch
            {
                return batcInfos;
            }
        }

        /// <summary>
        /// 获取往前近四周的周一的日期
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GetDate()
        {
            DateTime dateTime = DateTime.Now;
            int currentDayinWeek = (int)dateTime.DayOfWeek;
            int difference = currentDayinWeek;
            if (currentDayinWeek != 0)
                difference = 7 - currentDayinWeek;
            DateTime monday = dateTime.AddDays(-difference);
            List<string> date = new List<string>();
            //date.Add(dateTime.Month.ToString()+"-"+ dateTime.Day.ToString());

            for (int i = 0; i < 4; i++)
            {
                DateTime dateweekbefore = monday.AddDays(-7 * i);
                date.Add(dateweekbefore.Year.ToString() + "-" + dateweekbefore.Month.ToString("D2") + "-" + dateweekbefore.Day.ToString("D2"));
            }
            date.Reverse();
            return date;
        }

        /// <summary>
        /// 获取前四周每周产量
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetProduceQuantity()
        {
            DateTime today = DateTime.Now;
            List<string> dates = new List<string>();
            var outlineStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "OutLineStationCode").FirstOrDefault().propertyValue;

            dates.AddRange(await GetDate());
            string appenddex = " 00:00:00";

            List<int> quantity = new List<int>();
            List<DateTime> dateTimes = new List<DateTime>();
            try
            {
                for (int i = 0; i < dates.Count; i++)
                {
                    dateTimes.Add(DateTime.Parse( dates[i] + appenddex));
                }
                dateTimes.Add((DateTime)today);
            }
            catch (Exception ex)
            {

            }

            try
            {
                for (int i = 1; i < dateTimes.Count; i++)
                {
                    var passRecords = context.DC.Set<PassStationRecord>().Where(x => x.PassStatus == "pass" && x.StationCode == outlineStation).ToList()
                        .Where(r =>
                        {
                            DateTime parseDate;
                            return DateTime.TryParse(r.PassEndTime, out parseDate) &&
                            parseDate >= dateTimes[i - 1] && parseDate < dateTimes[i];
                        }).ToList();
                    quantity.Add(passRecords.Count);
                }
            }
            catch (Exception ex)
            {

            }
            return quantity;
        }

        /// <summary>
        /// 获取周计划生产数量
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetPlanEachWeek()
        {
            List<int> plan = new List<int>();
            try
            {
                var planconfig = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "Weekplan").FirstOrDefault().propertyValue;
                string[] eachweek = planconfig.Split('*');
                foreach (var pw in eachweek)
                {
                    plan.Add(Convert.ToInt16(pw));
                }
            }
            catch (Exception ex)
            {

            }
            return plan;
        }

        /// <summary>
        /// 拧紧数据映射
        /// </summary>
        /// <param name="datas"></param>
        /// <returns></returns>
        public async Task<List<TighteningData>> MapToTighteningDatas(List<TighteningRequest.Tighten> datas)
        {
            List<TighteningData> tighteningDatas = new List<TighteningData>();

            foreach (var data in datas)
            {
                TighteningData tighteningData = new TighteningData();
                tighteningData.TID = data.ID;
                tighteningData.toolSerialNum = data.toolSerialNum;
                tighteningData.tighteningID = data.tighteningID;
                tighteningData.tool_id = data.tool_id;
                tighteningData.sn = data.vin;
                tighteningData.project_name = data.project_name;
                tighteningData.torque = data.torque;
                tighteningData.angle = data.angle;
                tighteningData.tightening_status = data.tightening_status;
                tighteningData.rawdata_time = data.rawdata_time;
                tighteningData.screw_id = data.screw_id;
                tighteningData.PointNum = data.PointNum;
                tighteningData.angle_offset = data.angle_offset;
                tighteningData.ArrTorque = data.ArrTorque;
                tighteningData.upload_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                tighteningData.upload_status = data.upload_status;
                tighteningData.CreateTime = DateTime.Now;
                tighteningDatas.Add(tighteningData);

            }
            return tighteningDatas;
        }


        /// <summary>
        /// 物料解绑操作
        /// </summary>
        /// <param name="AllRepaiInfos"></param>
        /// <returns></returns>
        public async Task<ResponseBase> LooseMaterialBindRecord(RepairRequest.LooseMaterialRequest AllRepaiInfos)
        { 
           
            try
            {

                //先给工厂mes端传递解绑信息
                await FmesUnbind(AllRepaiInfos);

                //本地数据库解绑
                var localLooseResult = await LooseLocalBindRecord(AllRepaiInfos.RepairMaterialInfos);
                if(!localLooseResult.Success)
                     return localLooseResult;

                //生成返修重绑记录
                var createresult =  await CreateRepairRecord(AllRepaiInfos);
                if(!createresult.Success)
                    return createresult;


                //生成托盘和sn绑定记录，用于过站
                var traybindSNresult = await CreateTrayBindVSNData(createresult.Mesg, AllRepaiInfos);
                return traybindSNresult;

            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }



        /// <summary>
        /// 将解绑信息上传至工厂MES
        /// </summary>
        /// <param name="AllRepaiInfos"></param>
        /// <returns></returns>
        private async Task<ResponseBase> FmesUnbind(RepairRequest.LooseMaterialRequest AllRepaiInfos)
        {
            StationLogRecord stationLog = new StationLogRecord();
            LooseBind.FMESLooseRequest res = new LooseBind.FMESLooseRequest();
            res.unbindAssemblyCodes = new List<string>();
            res.factoryCode = factoryCode;
            res.lineCode = _LineCode;
            res.requestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            res.timer = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            foreach (var repairinfo in AllRepaiInfos.RepairMaterialInfos)
            {
                res.unbindAssemblyCodes.Add(repairinfo.AssembleSN);
            }
            res.snNumber = AllRepaiInfos.SN;

            string psd = JsonConvert.SerializeObject(res);
            string value = await httpService.PostDataAsync("http://" + mesIP + ":" + mesPort + "/api/product/Product_Information", psd);
            try
            {
                NormalResponse.ResponseUnbind response = JsonConvert.DeserializeObject<NormalResponse.ResponseUnbind>(value);
                if (response.code == "000000")
                {
                    await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                        AllRepaiInfos.SN, "good", response.data + response.mesg);
                    return new ResponseBase(true, response.data + response.mesg);
                }
                else
                    await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                        AllRepaiInfos.SN, "bad", response.data + response.mesg);
                return new ResponseBase(false, response.data + response.mesg);
            }
            catch (Exception ex)
            {
                await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                         AllRepaiInfos.SN, "bad", ex.Message);
                return new ResponseBase(false,ex.Message);
            }
        }

        /// <summary>
        /// 本地解绑物料记录
        /// </summary>
        /// <param name="RepairMaterialInfos"></param>
        /// <returns></returns>
        private async Task<ResponseBase> LooseLocalBindRecord(List<RepairInfo> RepairMaterialInfos)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                foreach (var repairinfo in RepairMaterialInfos)
                {
                    var record = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == repairinfo.AssembleSN).FirstOrDefault();
                    if (repairinfo.selected)
                        record.AssemblyMaterialSn += "unbind";
                    context.DC.SaveChanges();
                }
                return new ResponseBase(true, "本地解绑完成");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }

        /// <summary>
        /// 创建返修记录
        /// </summary>
        /// <param name="AllRepaiInfos"></param>
        /// <returns></returns>
        private async Task<ResponseBase> CreateRepairRecord(RepairRequest.LooseMaterialRequest AllRepaiInfos)
        {
            RepairRecord repairRecord = new RepairRecord();
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                repairRecord.LineCode = AllRepaiInfos.lineCode;
                repairRecord.OperationCode = AllRepaiInfos.stationCode;
                repairRecord.OldSN = AllRepaiInfos.SN;
                repairRecord.TZMaterialCode = AllRepaiInfos.TZMaterialCode;
                var SNRes = await codeCreateService.CreateCode("backupcode_product", 1);
                if (!SNRes.Success)
                {
                    await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                            AllRepaiInfos.SN, "bad", "获取返修后新的SN码失败：" + SNRes.Mesg);
                    return new ResponseBase(false, "获取返修后新的SN码失败：" + SNRes.Mesg);
                }
                repairRecord.CurrentSN = SNRes.Mesg;
                repairRecord.uploadTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                context.DC.Set<RepairRecord>().Add(repairRecord);
                context.DC.SaveChanges();
                await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                             AllRepaiInfos.SN, "good", "电机" + AllRepaiInfos.TZMaterialCode + "返修记录生成成功,新的SN号为：" + SNRes.Mesg);
                return new ResponseBase(true,SNRes.Mesg);

            }
            catch (Exception ex) 
            {
                await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                            AllRepaiInfos.SN, "bad", "生成返修记录异常" + ex.Message);
                return new ResponseBase(false, "生成返修记录异常"+ex.Message);
            }
        }

        /// <summary>
        /// 生成新的托盘sn号绑定记录
        /// </summary>
        /// <param name="NewSN"></param>
        /// <param name="AllRepaiInfos"></param>
        /// <returns></returns>
        private async Task<ResponseBase> CreateTrayBindVSNData(string NewSN, RepairRequest.LooseMaterialRequest AllRepaiInfos)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                var OldRecord = context.DC.Set<TrayBindVSN>().Where(x=>x.VSN==AllRepaiInfos.SN).FirstOrDefault();
                if (OldRecord==null)
                {
                    await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                            AllRepaiInfos.SN, "bad", "此电机未执行过上线绑定");
                    return new ResponseBase(false, "此电机未执行过上线绑定");
                }
                TrayBindVSN trayBindVSN = new TrayBindVSN();
                trayBindVSN.VSN = NewSN;
                trayBindVSN.TrayCode = OldRecord.TrayCode;
                trayBindVSN.OrderCode = OldRecord.OrderCode;
                trayBindVSN.ScheduleCode = OldRecord.ScheduleCode;
                trayBindVSN.LineCode = OldRecord.LineCode;
                trayBindVSN.TrayStation = OldRecord.TrayStation;
                trayBindVSN.BindStatus = Model.TrayBindStatusEnum.BIND;
                context.DC.Set<TrayBindVSN>().Add(trayBindVSN);
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                await stationlogadd(stationLog, AllRepaiInfos.lineCode, AllRepaiInfos.stationCode,
                            AllRepaiInfos.SN, "bad", "生成新托盘sn绑定记录异常" + ex.Message);
                return new ResponseBase(false, "生成新托盘sn绑定记录异常" + ex.Message);
            }
        }

        public async Task<bool> stationlogadd(StationLogRecord stationLog, string linecode, string stationCode, string sn, string logtype, string mesg)
        {
            stationLog.LogType = logtype;
            stationLog.StationCode = stationCode;
            stationLog.LineCode = linecode;
            stationLog.Log = mesg;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            context.DC.Set<StationLogRecord>().Add(stationLog);
            await context.DC.SaveChangesAsync();
            return true;
        }


        public async Task<bool> stationlogadd2(StationLogRecord stationLog, string linecode, string stationCode, string sn, string logtype, string mesg)
        {
            stationLog.LogType = logtype;
            stationLog.StationCode = stationCode;
            stationLog.LineCode = linecode;
            stationLog.Log = mesg;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            context.DC.Set<StationLogRecord>().Add(stationLog);
            await context.DC.SaveChangesAsync();
            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(stationLog.LineCode, stationLog.StationCode));
            return true;
        }


        public async Task<bool> stationlogadd3(string linecode, string stationCode, string sn, string logtype, string mesg)
        {
            StationLogRecord stationLog = new StationLogRecord();
            stationLog.LogType = logtype;
            stationLog.StationCode = stationCode;
            stationLog.LineCode = linecode;
            stationLog.Log = mesg;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            context.DC.Set<StationLogRecord>().Add(stationLog);
            await context.DC.SaveChangesAsync();
            await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(stationLog.LineCode, stationLog.StationCode));
            return true;
        }

        public async Task<bool> stationlogadd4(string linecode, string stationCode, string sn, string logtype, string mesg)
        {
            StationLogRecord stationLog = new StationLogRecord();
            stationLog.LogType = logtype;
            stationLog.StationCode = stationCode;
            stationLog.LineCode = linecode;
            stationLog.Log = mesg;
            stationLog.CreateTime = DateTime.Now;
            stationLog.Date_Time = DateTime.Now;
            context.DC.Set<StationLogRecord>().Add(stationLog);
            await context.DC.SaveChangesAsync();
            //await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(stationLog.LineCode, stationLog.StationCode));
            return true;
        }
        /// <summary>
        /// 通过sn号查询所有的信息
        /// </summary>
        /// <returns></returns>
        public async Task<UIResponse.FinishAllData> GetAllFinishedataBySN(UIRequest.PassRecordUI res)
        {
            UIResponse.FinishAllData finishAllData = new UIResponse.FinishAllData();

            //List<UIResponse.FinishPassRecord> finishes = new List<UIResponse.FinishPassRecord>();
            finishAllData.passRecords = new List<UIResponse.FinishPassRecord>();
            finishAllData.materialRecords = new List<UIResponse.MaterialRecord>();
            finishAllData.processDataRecords = new List<UIResponse.ProcessDataRecord>();
            finishAllData.batcInfoRecords = new List<UIResponse.BatcInfo>();
            finishAllData.essentialBOMs = new List<EssentialBOM>();
            try
            {
                //追溯到它的电机装配SN,用于获取整线信息
                var SearchTZSNResult = await SearchTZSN(res.SN);
                string TZSN = string.Empty;
                if (SearchTZSNResult.Success) 
                    TZSN = SearchTZSNResult.Mesg;
                else 
                    TZSN = res.SN;

                //后续的查询中都以电机SN去查询，当然也要注意可能查不到电机sn的情况，这时就会按当前传入SN去查询

                finishAllData.passRecords.AddRange(await FinishPassRecords(TZSN));
                var AssemblyInfos = await UIMaterialRecords(TZSN);
                finishAllData.materialRecords.AddRange(AssemblyInfos);
                finishAllData.processDataRecords.AddRange(await UIProcessDataRecords(TZSN));
                finishAllData.essentialBOMs.AddRange(await GetEssentialBOMs(TZSN));

                //轴系生产加工数据上传
                var ZXmergStation = context.DC.Set<CustomConfig>().Where(x=>x.customProperty== "boxmergStationCode").FirstOrDefault()?.propertyValue;
                var ZXMaterialAssemblyInfos = AssemblyInfos.Where(x=>x.stationId==ZXmergStation).ToList();
                finishAllData.processDataRecords.AddRange(await GearProcessData(ZXMaterialAssemblyInfos));
                finishAllData.processDataRecords.AddRange(await GetGearTighteningData(ZXMaterialAssemblyInfos));


                //轴系批次数据上传
                finishAllData.batcInfoRecords.AddRange(await UIBatchRecords(AssemblyInfos));
                finishAllData.batcInfoRecords.AddRange(await CSBatchRecords(TZSN));
                //关键工位BOM获取

                return finishAllData;
            }
            catch (Exception ex)
            {
                return finishAllData;
            }
        }


        /// <summary>
        /// 轴系拧紧数据
        /// </summary>
        /// <param name="assemblys"></param>
        /// <returns></returns>
        public async Task<List<ProcessDataRecord>> GetGearTighteningData(List<UIResponse.MaterialRecord> assemblys)
        {
            List<ProcessDataRecord> processDataRecords = new List<ProcessDataRecord>();
            try
            {
                foreach (var assembly in assemblys)
                {
                    string sn =  assembly.materialSN.Substring(0,11)+ assembly.materialSN.Substring(18, 14);
                    var tigheteningdatas = context.DC.Set<TighteningData>().Where(x=>x.sn==sn) .ToList();
                    foreach (var t in tigheteningdatas)
                    {
                        ProcessDataRecord processDataRecord1 = new ProcessDataRecord();
                        ProcessDataRecord processDataRecord2 = new ProcessDataRecord();
                        string processName = context.DC.Set<Station>().Where(x => x.StationCode == t.project_name).FirstOrDefault()?.StationName;
                        if (processName==null)
                            processName = t.project_name;
                        processDataRecord1.processId = t.project_name;
                        processDataRecord1.processName = processName;
                        processDataRecord1.paramName = $"拧紧轴{t.screw_id}角度";
                        processDataRecord1.value = t.angle;
                        processDataRecords.Add(processDataRecord1);
                        processDataRecord2.processId = t.project_name;
                        processDataRecord2.processName = processName;
                        processDataRecord2.paramName = $"拧紧轴{t.screw_id}扭矩";
                        processDataRecord2.value = t.torque;
                        processDataRecords.Add(processDataRecord2);

                    }
                }

            }
            catch 
            {
                return processDataRecords;
            }
            return processDataRecords;
        }
       

        /// <summary>
        /// 获取关键物料BOM
        /// </summary>
        /// <param name="TZSN"></param>
        /// <returns></returns>
        public async Task<List<EssentialBOM>> GetEssentialBOMs(string TZSN)
        {
            List<EssentialBOM> essentialBOMs = new List<EssentialBOM>();
            var order = context.DC.Set<TrayBindVSN>().Where(x=>x.VSN==TZSN).FirstOrDefault()?.OrderCode;
            var boms = context.DC.Set<ProductBOM>().Where(x=>x.OrderCode==order&&(x.OperationCode=="2-OP3010"||x.OperationCode=="2-OP4040")).ToList();
            foreach (var bom in boms)
            {
                EssentialBOM essentialBOM = new EssentialBOM();
                essentialBOM.OperationCode = bom.OperationCode;
                essentialBOM.AssemblyMaterialCode = bom.AssemblyMaterialCode;
                essentialBOM.AssemblyMaterialName = bom.AssemblyMaterialName;
                essentialBOM.AssemblyRegex = bom.AssemblyMaterialRegex;
                essentialBOMs.Add(essentialBOM);
            }
            return essentialBOMs;
        }

        /// <summary>
        /// 获取轴系加工数据
        /// </summary>
        /// <param name="assemblys"></param>
        /// <returns></returns>
        public async Task<List<ProcessDataRecord>> GearProcessData(List<MaterialRecord> assemblys)
        {
            List<ProcessDataRecord> AssemblysprocessDatas = new List<ProcessDataRecord>();
            try
            {
                //var boxmergStationCode = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "boxmergStationCode").FirstOrDefault()?.propertyValue;
                foreach (var assembly in assemblys)
                {
                    var GearPDs = context.DC.Set<MaterialPD>().Where(x=>x.CurrentSN==assembly.materialSN).ToList();
                    if (GearPDs.Count == 0)
                        continue;
                    foreach (var PD in GearPDs)
                    {
                        int firstStar;
                        try
                        {
                            firstStar = PD.PDname.IndexOf('*');
                        }
                        catch
                        {
                            firstStar = -1;
                        }
                        
                        if(firstStar == -1)
                            continue;
                        string materialName = PD.PDname.Substring(0, firstStar);
                        string nameTable = PD.PDname.Substring(firstStar + 1);
                        string[] names = nameTable.Split('*');
                        string[] datas = PD.PDdata.Split('*');
                        for (int i=0;i<names.Length;i++)
                        {
                            ProcessDataRecord processDataRecord = new ProcessDataRecord();
                            processDataRecord.processId = PD.OperationCode;
                            processDataRecord.processName =PD.OperationName;
                            processDataRecord.paramName = materialName+names[i];
                            processDataRecord.value = datas[i];
                            AssemblysprocessDatas.Add(processDataRecord);
                        }
                    }
                }
                return AssemblysprocessDatas;
            }
            catch
            {
                return AssemblysprocessDatas;
            }
        }

        /// <summary>
        /// 获取SN对应电机装配线上线的SN号
        /// </summary>
        /// <param name="CurrentSN"></param>
        /// <returns></returns>
        public async Task<ResponseBase> SearchTZSN(string CurrentSN)
        {
            try
            {
                var CurrentSNFirstStation = context.DC.Set<TrayBindVSN>().Where(x=>x.VSN== CurrentSN).FirstOrDefault();
                if(CurrentSNFirstStation == null)
                    return new ResponseBase(false, $"SN{CurrentSN}未执行过上线绑定");
                var TZFirstStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "TZFirstStationCode").First().propertyValue;
                if(TZFirstStation == CurrentSNFirstStation.TrayStation)
                    return new ResponseBase(true, CurrentSN);
                var QXFirstStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "QXFirstStationCode").First().propertyValue;
                if(QXFirstStation == CurrentSNFirstStation.TrayStation)
                {
                    var PadSelectStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "PadSelectStation").First().propertyValue;
                    
                    var QXMaterialRecord = context.DC.Set<MaterialBindRecord>().Where(x=>x.AssemblyMaterialSn== CurrentSN&&x.StationCode==PadSelectStation).FirstOrDefault();
                    if (QXMaterialRecord == null)
                        return new ResponseBase(true, CurrentSN);
                    return new ResponseBase(true, QXMaterialRecord.SnNumber);
                }
                var CSFirstStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "CSFirstStationCode").First().propertyValue;
                if(CSFirstStation == CurrentSNFirstStation.TrayStation)
                {
                    var MaterialRecord = context.DC.Set<MaterialBindRecord>().Where(x => x.StationCode == CSFirstStation && x.SnNumber == CurrentSN).FirstOrDefault();
                    if(MaterialRecord == null)
                        return new ResponseBase(true, CurrentSN);
                    return new ResponseBase(true, MaterialRecord.AssemblyMaterialSn);
                }
                return new ResponseBase(false, "需确定是否为返修件");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false,ex.Message);
            }
        }

        /// <summary>
        /// 当前生产工单下各个生产工位的产出数量
        /// </summary>
        /// <returns></returns>
        public async Task<List<StationInfo>> GetStationInfos()
        {
            List<StationInfo> stationInfos = new List<StationInfo>();
            try
            {
                var stations = context.DC.Set<Station>().ToList();

                //获取当前工单
                var orderInfo = context.DC.Set<Order_Model>().Where(x => x.MOrderStatus == "3").FirstOrDefault();
                foreach (var station in stations)
                {
                  StationInfo info = new StationInfo();
                  int stationoutputCount = context.DC.Set<PassStationRecord>().Where(x=>x.OrderCode==orderInfo.OrderCode&&x.StationCode==station.StationCode&&x.PassStatus=="pass").ToList().Count();
                    if (stationoutputCount == 0)
                        continue;
                    info.processId = station.StationCode;
                    info.processName = station.StationName;
                    info.workOrder = orderInfo.OrderCode;
                    info.productionCount = stationoutputCount.ToString();
                    stationInfos.Add(info);
                }
                return stationInfos;
            }
            catch (Exception ex)
            {
                return stationInfos;
            }
        }

        /// <summary>
        /// 获取计划产出数量和实际产出
        /// </summary>
        /// <returns></returns>
        public async Task<UIResponse.ActualOutputAndPlan> GetOrderOutput()
        {
            UIResponse.ActualOutputAndPlan actualOutputAndPlan = new UIResponse.ActualOutputAndPlan();
            try
            {
                
                var OutputStationCode = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "OutLineStationCode").FirstOrDefault().propertyValue;
                if (OutputStationCode == null) return actualOutputAndPlan;
                var orderInfo = context.DC.Set<Order_Model>().Where(x => x.MOrderStatus == "3").FirstOrDefault();
                if (orderInfo == null) return actualOutputAndPlan;
                var OutputQuantity = context.DC.Set<PassStationRecord>().Where(x => x.StationCode == OutputStationCode && x.PassStatus == "pass" && x.OrderCode == orderInfo.OrderCode).ToList().Count.ToString();
                actualOutputAndPlan.OrderOutput = OutputQuantity;
                actualOutputAndPlan.OrderPlanQuantity = orderInfo.OrderQty;
                return actualOutputAndPlan;
            }
            catch
            {
                return actualOutputAndPlan;
            }
        }
        
        /// <summary>
        /// 手动扫码进站校验
        /// </summary>
        /// <param name="stationCode"></param>
        /// <param name="TZmaterialCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckScanPass(string stationCode,string TZmaterialCode)
        {
            var station = context.DC.Set<Station>().Where(x => x.StationManagerID == "trueman" && x.StationCode == stationCode).FirstOrDefault();
            if (station == null)
                return new ResponseBase(false, "");
           var TZregex = context.DC.Set<CustomConfig>().Where(x=>x.customProperty=="TZRegex").FirstOrDefault();
            if(TZregex == null)
                return new ResponseBase(false,"");
            if (Regex.IsMatch(TZmaterialCode, TZregex.propertyValue))
                return new ResponseBase(true, "");
            return new ResponseBase(false, "");
        }

        /// <summary>
        /// 校验是否为后箱体
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckPadSelectedStation(SelectPadResquest res)
        {
            StationLogRecord stationLog = new StationLogRecord();
            var IsTZ = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "TZRegex").FirstOrDefault();
            if (IsTZ == null)
            {
                await stationlogadd(stationLog, res.lineCode, res.stationCode, res.scanData, "bad", "未维护电机过站正则");
                return new ResponseBase(false, "过站电机正则未维护");         
            }
            if(!Regex.IsMatch(res.scanData,IsTZ.propertyValue))
                return new ResponseBase(false, "非电机扫码");
            
            return new ResponseBase(true, "");
        }


        /// <summary>
        /// 校验是否为前箱体
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckIsQX(SelectPadResquest res)
        {
            StationLogRecord stationLog = new StationLogRecord();
            var IsQX = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "QXRegex").FirstOrDefault();
            if (IsQX == null)
            {
                await stationlogadd(stationLog, res.lineCode, res.stationCode, res.scanData, "bad", "未维护前箱过站正则");
                return new ResponseBase(false, "前箱过站正则未维护");
            }
            if (!Regex.IsMatch(res.scanData, IsQX.propertyValue))
                return new ResponseBase(false, "非前箱体扫码");

            return new ResponseBase(true, "");
        }

        /// <summary>
        /// 获取选垫类型
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GetPadTypes()
        {
            List<string> padTypes = new List<string>();
            try
            {
                var CSQ = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "CSQType").FirstOrDefault()?.propertyValue;
                padTypes.Add(CSQ);
                var FZ = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "FZType").FirstOrDefault()?.propertyValue;
                padTypes.Add(FZ);
                var FDJ = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "FDJType").FirstOrDefault()?.propertyValue;
                padTypes.Add(FDJ);
                return padTypes;
            }
            catch
            {
                return padTypes;
            }
        }
    
        /// <summary>
        /// 从扫码内容中获取到指定信息
        /// </summary>
        /// <param name="startString"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        public async Task<ResponseBase> GetInfoFromScanData(string startString , BatchComplitionResponse.BatchUpdateInfo info)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                int startIndex = info.scanCode.IndexOf(startString);
                if (startIndex == -1)
                {
                    await stationlogadd(stationLog, info.stationCode, info.stationCode, "",
                        "bad", "未在扫入条码中查到" + startString+"编码内容; " + info.scanCode);
                    return new ResponseBase(false, "未在扫入条码中查到物料编码，扫入内容; " + info.scanCode);
                }
                startIndex += startString.Length;
                int endIndex = info.scanCode.IndexOf(";", startIndex);
                if (endIndex == -1)
                    endIndex = info.scanCode.Length - 1;
                string Code = info.scanCode.Substring(startIndex, endIndex-startIndex);
                return new ResponseBase(true, Code);
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
            
        }

        /// <summary>
        /// 校验批次是否重复
        /// </summary>
        /// <param name="materialCode"></param>
        /// <param name="batchCode"></param>
        /// <param name="stationCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> JudgeBatchRepeat(string materialCode,string batchCode,string stationCode)
        {
            try
            {
                var batchCompilation = context.DC.Set<BatchCompilations>().Where(x => x.stationCode == stationCode && x.materialCode == materialCode && x.batchCode == batchCode).FirstOrDefault();
                if(batchCompilation != null)
                    return new ResponseBase(false, "此批次料已完成过上料");
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }


        /// <summary>
        /// 出站前将批次信息与SN绑定
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> BatchBindSN(PassStationRequestSup passStationRequestSup)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                //双工位需要前箱不绑定批次信息
                var isQX = await CheckIsPassDoubleStation(passStationRequestSup);
                if (isQX.Success)
                    return isQX;

                ResponseBase judgeIsUseUp = new ResponseBase(true,null);
                string useup_materialCode = string.Empty;
                string useup_batchCode = string.Empty;
                List<BatchInfor> batchs = new List<BatchInfor>();
                var batchCompilations = context.DC.Set<BatchCompilations>().Where(x => x.stationCode == passStationRequestSup.stationCode&&x.isUse==true).ToList();
                //校验是否存在黑名单物料
                var judgeblacklist =await CheckIsBlacklist(batchCompilations, passStationRequestSup.stationCode);
                if (!judgeblacklist.Success)
                    return judgeblacklist;

                //在2-BOP1020-0工位要校验两个物料厂家是否一致不一致需要报错
                if(passStationRequestSup.stationCode== "2-BOP1020-0")
                {
                    var material1 = batchCompilations.Where(x=>x.materialCode== "12421136-00").FirstOrDefault();
                    if(material1==null)
                        return new ResponseBase(false, $"工位{passStationRequestSup.stationCode}缺少NT33-2146314_半轴齿轮_M00000");
                    var material2 = batchCompilations.Where(x => x.materialCode == "12421137-00").FirstOrDefault();
                    if (material2 == null)
                        return new ResponseBase(false, $"工位{passStationRequestSup.stationCode}缺少NT33-2146312_行星齿轮_M00000");
                    if(material1.Filed1!=material2.Filed1)
                        return new ResponseBase(false, $"工位{passStationRequestSup.stationCode}NT33-2146312_行星齿轮_M00000与NT33-2146314_半轴齿轮_M00000厂家不一致");
                }

                if(batchCompilations.Count==0)
                    return new ResponseBase(true, "");
                foreach (var batchinfo in batchCompilations)
                {
                    var judgeBatchRedundantBind = await BatchRedundantBinding(passStationRequestSup.snNumber, batchinfo);
                    if (!judgeBatchRedundantBind.Success)
                        continue;
                    judgeIsUseUp =await IsBatchUsedUp(batchinfo);
                    if (!judgeIsUseUp.Success)
                    {
                        useup_batchCode = batchinfo.batchCode;
                        useup_materialCode = batchinfo.materialCode;
                        break;
                    }
                    BatchInfor batch = new BatchInfor();
                    batch.CurrentSN = passStationRequestSup.snNumber;
                    batch.BatchCode = batchinfo.batchCode;
                    batch.orderCode = passStationRequestSup.orderCode;
                    batch.schduleCode = passStationRequestSup.scheduleCode;
                    batch.CreateTime = DateTime.Now;
                    batch.OperationCode = passStationRequestSup.stationCode;
                    batch.OperationName = batchinfo.materialCode;
                    batch.SingleConsumption = batchinfo.batchSingleCostQty;
                    batch.LineCode = batchinfo.lineCode;
                    batchs.Add(batch);
                    //扣料
                    await SubtractBatchNum(batchinfo);
                }
                string UsedBatch = string.Empty;
                foreach (var batch in batchs)
                {
                    UsedBatch += $"[{batch.BatchCode}]";
                }
                await stationlogadd(stationLog, passStationRequestSup.lineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "good", $"SN:{passStationRequestSup.snNumber}使用批次物料{UsedBatch}");

                context.DC.Set<BatchInfor>().AddRange(batchs);
                context.DC.SaveChanges();
                if(!judgeIsUseUp.Success)
                    return new ResponseBase(false, $"物料{useup_materialCode}批次{useup_batchCode}已用完，请添加新的批次物料");
                await notification.Clients.All.SendAsync("ReceiveMessage", new Notice(passStationRequestSup.lineCode, passStationRequestSup.stationCode));
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                await stationlogadd2(stationLog, passStationRequestSup.lineCode, passStationRequestSup.stationCode, passStationRequestSup.snNumber, "good", ex.Message);
                return new ResponseBase(false,ex.Message);
            }
        }
    
        /// <summary>
        /// 双工位前箱不绑定批次信息
        /// </summary>
        /// <param name="passStationRequestSup"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckIsPassDoubleStation(PassStationRequestSup passStationRequestSup)
        {
            var QXBindRecord = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == passStationRequestSup.snNumber && x.StationCode == "2-OP3180-0").FirstOrDefault();
            if (QXBindRecord == null)
                return new ResponseBase(false, "");
            return new ResponseBase(true, "");
        }

        /// <summary>
        /// 校验是否存在黑名单物料
        /// </summary>
        /// <param name="batchCompilations"></param>
        /// <param name="stationCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckIsBlacklist(List<BatchCompilations> batchCompilations,string stationCode)
        {
            if (batchCompilations.Count < 1)
                return new ResponseBase(true, "");
            var blacklist = context.DC.Set<BatchBlacklist>().Where(x=>x.stationCode==stationCode).ToList();
            foreach(var blackbatch in blacklist)
            {
                if (batchCompilations.Any(x => x.Filed1 == blackbatch.supplementCode && x.materialCode == blackbatch.materialCode))
                    return new ResponseBase(false, $"存在黑名单物料{blackbatch.materialName},物料编码{blackbatch.materialCode},供应商{blackbatch.supplementCode},");
            }
            return new ResponseBase(true, "");
        }

        /// <summary>
        /// 校验是否重复绑定
        /// </summary>
        /// <param name="SN"></param>
        /// <param name="batchinfo"></param>
        /// <returns></returns>
        public async Task<ResponseBase> BatchRedundantBinding(string SN,BatchCompilations batchinfo)
        {
            try
            {
                var batchbind_exist = context.DC.Set<BatchInfor>().Where(x=>x.CurrentSN == SN&&x.BatchCode==batchinfo.batchCode&&x.OperationCode==batchinfo.stationCode).ToList();
                if (batchbind_exist.Count==0)
                    return new ResponseBase(true,"");
                return new ResponseBase(false, $"{SN}已经完成批次{batchinfo.batchCode}的批次绑定");
            }
            catch (Exception ex)
            {
                return new ResponseBase (false,ex.Message);
            }
        }


        public async Task<ResponseBase> SubtractBatchNum(BatchCompilations batchinfo)
        {
            try
            {
                var thisbatch = context.DC.Set<BatchCompilations>().Where(x=>x.ID==batchinfo.ID).First();
                thisbatch.batchMarginQty = (Convert.ToInt32(thisbatch.batchMarginQty)-Convert.ToInt32(thisbatch.batchSingleCostQty)).ToString();
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch(Exception ex) 
            {
                return new ResponseBase(false, ex.Message);
            }
        }

        /// <summary>
        /// 批次达量判断
        /// </summary>
        /// <param name="stationCode"></param>
        /// <param name="batchCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> IsBatchUsedUp(BatchCompilations batchinfo)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {

                
                var BatchInfo = context.DC.Set<BatchCompilations>().Where(x => x.ID== batchinfo.ID).FirstOrDefault();
                int singleCost = Convert.ToInt32(BatchInfo.batchSingleCostQty);
                int margin = Convert.ToInt32(BatchInfo.batchMarginQty);
                if (margin < singleCost)
                {
                    await stationlogadd2(stationLog, "", batchinfo.stationCode, "", "bad", $"批次{batchinfo.batchCode}物料已耗尽，请补充");
                    return new ResponseBase(false, $"批次{batchinfo.batchCode}物料已耗尽，请补充");
                }
                else if (margin  < singleCost * 5)
                {
                    await stationlogadd2(stationLog, "", batchinfo.stationCode, "", "bad", $"批次{batchinfo.batchCode}物料剩余{margin},即将耗尽，请补充");
                    return new ResponseBase(true, $"批次{batchinfo.batchCode}物料即将耗尽，请补充");
                }
                else
                    return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                await stationlogadd2(stationLog, "", batchinfo.stationCode, "", "bad", ex.Message);
                return new ResponseBase(false, ex.Message);
            }
        }

        /// <summary>
        /// 保存选垫结果
        /// </summary>
        /// <param name="selectPad"></param>
        /// <returns></returns>
        public ResponseBase SavePadSelectResult(SelectPadResquest selectPad)
        {
            try
            {
                MaterialPD materialPD = new MaterialPD();
                materialPD.LineCode = selectPad.lineCode;
                materialPD.OperationCode = selectPad.stationCode;
                materialPD.CurrentSN = selectPad.TZSN;
                materialPD.AnotherSN = selectPad.QXSN;
                materialPD.PDname = "差速器选垫*副轴选垫*发动机轴选垫";
                materialPD.PDdata = selectPad.CType + "*" + selectPad.FZType + "*" + selectPad.FType;
                context.DC.Set<MaterialPD>().Add(materialPD);
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }

        /// <summary>
        /// 前箱测深数据
        /// </summary>
        /// <param name="QXSN"></param>
        /// <returns></returns>
        public async Task<List<string>> QXPadSelectData(string QXSN)
        {
            try
            {
                //获取前箱测深工位号
                var CSStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "QXCSStationCode").First().propertyValue;
                var qx_data = context.DC.Set<MaterialPD>().Where(x => x.OperationCode == CSStation && x.CurrentSN == QXSN).OrderByDescending(x => x.ID).First();
                char[] delimiterChars = { '*' };
                string[] OrignalData = qx_data.PDdata.Split(delimiterChars);
                List<string> datas = OrignalData.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
                var material = context.DC.Set<MaterialBindRecord>().Where(x=>x.SnNumber==QXSN&&x.StationCode=="2-OP3020-0").OrderByDescending(x => x.ID).First().AssemblyMaterialSn;
                datas.Add(material);
                return datas;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 后箱测高数据
        /// </summary>
        /// <param name="TZSN"></param>
        /// <returns></returns>
        public async Task<List<string>> TZPadSelectData(string TZSN)
        {
            try
            {
                //获取前箱测深工位号
                var CHStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "TZCHStationCode").First().propertyValue;
                var tz_data = context.DC.Set<MaterialPD>().Where(x => x.OperationCode == CHStation && x.CurrentSN == TZSN).OrderByDescending(x => x.ID).First();
                char[] delimiterChars = { '*' };
                string[] OrignalData = tz_data.PDdata.Split(delimiterChars);
                List<string> datas = OrignalData.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
                var material = context.DC.Set<MaterialBindRecord>().Where(x => x.SnNumber == TZSN && x.StationCode == "2-OP3010-0").OrderByDescending(x => x.ID).First().AssemblyMaterialSn;
                datas.Add(material);
                return datas;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 自动选垫
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public async Task<SelectPadResquest> AutoSelectPad(SelectPadResquest res,string TZSN)
        {
            SelectPadResquest selectPad = new SelectPadResquest();
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                var QXFirstStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "QXFirstStationCode").FirstOrDefault()?.propertyValue;
                string QXAssemblySN = context.DC.Set<MaterialBindRecord>().Where(x => x.StationCode == QXFirstStation && x.SnNumber == res.QXSN).FirstOrDefault()?.AssemblyMaterialSn;
                if (QXAssemblySN == null)
                {
                    await stationlogadd(stationLog, res.lineCode, res.stationCode, "", "bad", $"前箱SN[{res.QXSN}]上线未执行绑定");
                    return selectPad;
                }
                res.QXAssmeblyCode = QXAssemblySN;
                //获取前箱测深工位号
                var CSStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "QXCSStationCode").First().propertyValue;
                //判断是否已完成过绑定
                var PadSelect_result_Exist = context.DC.Set<MaterialPD>().Where(x => x.AnotherSN == res.QXSN && x.OperationCode == res.stationCode).OrderByDescending(x => x.ID).FirstOrDefault();
                if (PadSelect_result_Exist != null)
                {
                    await  stationlogadd(stationLog, res.lineCode, res.stationCode, res.QXSN, "bad", "前箱SN[" + res.QXSN + "]已完成过选垫绑定");
                    return selectPad;
                }

                var MeasureDepth = context.DC.Set<MaterialPD>().Where(x => x.CurrentSN == res.QXSN && x.OperationCode == CSStation).OrderByDescending(x => x.ID).FirstOrDefault();
                if (MeasureDepth == null)
                {
                    await stationlogadd(stationLog, res.lineCode, res.stationCode, res.QXSN, "bad", "未查询到" + res.QXSN + "的测深记录");
                    return selectPad;
                }
                else
                {
                    char[] delimiterChars = { '*' };
                    string[] OrignalData = MeasureDepth.PDdata.Split(delimiterChars);
                    string[] datas = OrignalData.Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
                    //List<string> SelectTypes =await passStationService.GetPadTypes();
                    selectPad.QXAssmeblyCode = res.QXAssmeblyCode;
                    selectPad.QXSN = res.QXSN;
                    selectPad.LQC = datas[0];
                    selectPad.LQFZ = datas[1];
                    selectPad.LQF = datas[2];

                    //获取当前过站sn
                    ResponseComSN getTZSN = new ResponseComSN { Success=true,SN=TZSN};

                    //测电机轴高度工位
                    var CHStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "TZCHStationCode").First().propertyValue;

                    //绑定的电机物料信息
                    var TZFirstStation = context.DC.Set<CustomConfig>().Where(x => x.customProperty == "TZFirstStationCode").First().propertyValue;
                    var TZMaterialBindRecord = context.DC.Set<MaterialBindRecord>().Where(x => x.StationCode == TZFirstStation && x.SnNumber == getTZSN.SN).FirstOrDefault();
                    if (TZFirstStation == null)
                    {
                        await stationlogadd(stationLog, res.lineCode, res.stationCode, getTZSN.SN, "bad", "SN:[" + getTZSN.SN + "]上线未绑定电机号");
                        return selectPad;
                    }

                    //判断是否已完成过选垫绑定
                    var PadSelect_TZresult_Exist = context.DC.Set<MaterialPD>().Where(x => x.CurrentSN == getTZSN.SN && x.OperationCode == res.stationCode).OrderByDescending(x => x.ID).FirstOrDefault();
                    if (PadSelect_TZresult_Exist != null)
                    {
                        await stationlogadd(stationLog, res.lineCode, res.stationCode, getTZSN.SN, "bad", "后箱SN[" + getTZSN.SN + "]已完成过选垫绑定");
                        return selectPad;
                    }

                    var MeasureHigh = context.DC.Set<MaterialPD>().Where(x => x.CurrentSN == getTZSN.SN && x.OperationCode == CHStation).OrderByDescending(x => x.ID).FirstOrDefault();
                    if (MeasureHigh == null)
                    {
                        await stationlogadd(stationLog, res.lineCode, res.stationCode, getTZSN.SN, "bad", "未查询到" + getTZSN.SN + "的测高记录");
                        return selectPad;
                    }
                    else
                    {
                        //char[] delimiterChars = { '*' };
                        string[] TZOrignalData = MeasureHigh.PDdata.Split(delimiterChars);
                        string[] TZdatas = TZOrignalData.Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
                        List<string> SelectTypes = await GetPadTypes();
                        //selectPad.QXAssmeblyCode = res.QXAssmeblyCode;
                        selectPad.TZAssmeblyCode = TZMaterialBindRecord.AssemblyMaterialSn;
                        //selectPad.QXSN = res.QXSN;
                        selectPad.TZSN = getTZSN.SN;
                        selectPad.LHC = TZdatas[0];
                        selectPad.LHFZ = TZdatas[1];
                        selectPad.LHF = TZdatas[2];

                        double lqc = double.Parse(selectPad.LQC);//差速器深度
                        double lqfz = double.Parse(selectPad.LQFZ);//副轴深度
                        double lqf = double.Parse(selectPad.LQF);//发动机轴深度
                        double lhc = double.Parse(selectPad.LHC);//差速器高度
                        double lhfz = double.Parse(selectPad.LHFZ);//副轴深度
                        double lhf = double.Parse(selectPad.LHF);//发动机轴高度

                        double tcd = lqc - lhc + 0.05;//差速器区间左值
                        double tcu = lqc - lhc + 0.12;//差速器区间右值
                        double tfzd = lqfz - lhfz;//副轴区间左值
                        double tfzu = lqfz - lhfz + 0.1;//副轴区间右值
                        double tfu = lqf - lhf - 0.02;//发动机轴区间右值
                        double tfd = lqf - lhf - 0.08;//发动机=轴区间左值

                        selectPad.TCU = tcu.ToString("F2");
                        selectPad.TCD = tcd.ToString("F2");
                        selectPad.TFZU = tfzu.ToString("F2");
                        selectPad.TFZD = tfzd.ToString("F2");
                        selectPad.TFU = tfu.ToString("F2");
                        selectPad.TFD = tfd.ToString("F2");

                        if (SelectTypes[0] == "thick")//差速器选薄
                            selectPad.CType = (tcu - tcu % 0.05).ToString("F2");
                        else
                            selectPad.CType = (tcd - tcd % 0.05 + 0.05).ToString("F2");

                        if (SelectTypes[1] == "thick")//副轴选薄
                            selectPad.FZType = (tfzu - tfzu % 0.05).ToString("F2");
                        else
                            selectPad.FZType = (tfzd - tfzd % 0.05 + 0.05).ToString("F2");

                        if (SelectTypes[2] == "thick")//发动机轴选厚
                            selectPad.FType = (tfu - tfu % 0.05).ToString("F2");
                        else
                            selectPad.FType = (tfd - tfd % 0.05 + 0.05).ToString("F2");



                        selectPad.lineCode = res.lineCode;
                        selectPad.stationCode = res.stationCode;
                        selectPad.AutoSuccess = true;
                        SavePadSelectResult(selectPad);
                        await inverseControl.Clients.All.SendAsync("ReceiveMessage", new INotice(selectPad.TZSN, $"{selectPad.CType}*{selectPad.FZType}*{selectPad.FType}", "7"));
                        await stationlogadd(stationLog, res.lineCode, res.stationCode, "", "good", "前箱[" + selectPad.QXSN + "]测深值与后箱[" + selectPad.TZSN + "]测高值完成选垫绑定");
                        return selectPad;
                    }

                }
            }
            catch (Exception ex)
            {
                await stationlogadd(stationLog, res.lineCode, res.stationCode, res.scanData, "bad", ex.Message);
                return selectPad;
            }




        }

        /// <summary>
        /// 轴系入箱工位，批次信息绑定到SN上
        /// </summary>
        /// <param name="SN"></param>
        /// <param name="AssemblySN"></param>
        public void ChangeBatchBindSN(ParaAutoBindMaterial para)
        {
            if (para.stationCode != "2-OP3100-0")
                return;
            var AssemblySNs = context.DC.Set<MaterialBindRecord>().Where(x=>x.StationCode==para.stationCode&&x.SnNumber==para.SN).ToList();
            foreach( var assemblySN in AssemblySNs)
            {
                var orginalBatchInfo = context.DC.Set<BatchInfor>().Where(x => x.CurrentSN == assemblySN.AssemblyMaterialSn);
                foreach (var batch in orginalBatchInfo)
                {
                    batch.CreateBy = batch.CurrentSN;
                    batch.CurrentSN = para.SN;
                }
                context.DC.SaveChanges();
            }
            
        }

        /// <summary>
        /// 获取批量绑定的物料SN
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        public async Task<string> ScanBindMaterialToSupple(ParaAutoBindMaterial record)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                
                var CSQBindRecord = context.DC.Set<ScanMaterialSN>().Where(x => x.assemblyMaterialSN == record.AssemblyMaterialSNs).OrderByDescending(x=>x.ID). FirstOrDefault();
                if (CSQBindRecord == null)
                {
                    await stationlogadd2(stationLog, record.lineCode, record.stationCode, record.SN, "bad", $"差速器壳体{record.AssemblyMaterialSNs}没执行批量捆绑");
                    return null;
                }
                var ScanBindMaterials = context.DC.Set<ScanMaterialSN>().Where(x=>x.batchCode==CSQBindRecord.batchCode).ToList();
                string BindMaterials = string.Empty;
                foreach (var material in ScanBindMaterials)
                {
                    BindMaterials += material.assemblyMaterialSN + ",";
                }
                return BindMaterials.TrimEnd(',');
            }
            catch (Exception ex)
            {
                await stationlogadd2(stationLog, record.lineCode, record.stationCode, record.SN, "bad", $"获取批量绑定物料SN异常：{ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 通过电机号获取测试段SN
        /// </summary>
        /// <param name="TZCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> GetCSSNByTZCode(string TZCode,string lineCode ,string stationCode)
        {
            StationLogRecord stationLog = new StationLogRecord();
            try
            {
                //var CSAutoStation = context.DC.Set<CustomConfig>().Where(x=>x.customProperty== "CSFirstStationCode").FirstOrDefault()?.propertyValue; 
                //var CSManualStation = context.DC.Set<CustomConfig>().Where(x=>x.customProperty== "CSFirstStationCode-manual").FirstOrDefault()?.propertyValue;

                var ZPSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == TZCode).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
                if (ZPSN == null)
                {
                    await stationlogadd(stationLog, lineCode, stationCode, "", "bad", $"未查询到电机{TZCode}在装配段的上线绑定记录");
                    return new ResponseBase(false, TZCode);
                }

                var CSSN = context.DC.Set<MaterialBindRecord>().Where(x => x.AssemblyMaterialSn == ZPSN).OrderByDescending(x => x.ID).FirstOrDefault()?.SnNumber;
                if (CSSN == null)
                {
                    await stationlogadd(stationLog, lineCode, stationCode, "", "bad", $"查询到电机{TZCode}在装配段SN{ZPSN},但未查询到其在测试端上线绑定记录");
                    return new ResponseBase(false, TZCode);
                }

                return new ResponseBase(true, CSSN);
            }
            catch (Exception ex)
            {
                await stationlogadd(stationLog, lineCode, stationCode, "", "bad", ex.Message);

                return new ResponseBase(false, TZCode);
            }
          
                
        }


        
       

        /// <summary>
        /// 同步工厂物料信息
        /// </summary>
        /// <returns></returns>
        public async Task<ResponseBase> MaterialInfoAsync()
        {
            List<Material> materials = new List<Material>();
            try
            {
                MaterialRequest request = new MaterialRequest();
                string psd = JsonConvert.SerializeObject(request);
                string value =await httpService.PostDataAsync("http://"+mesIP+":"+mesPort+ "/api/base/Base_Information", psd);
                MaterialResponse response = JsonConvert.DeserializeObject<MaterialResponse>(value);
                foreach(var material in response.data)
                {
                    var exist_material = context.DC.Set<Material>().Where(x => x.MaterialCode == material.materialCode).ToList();
                    if (exist_material.Count != 0)
                        continue;
                    Material newmaterial = new Material();
                    newmaterial.MaterialCode = material.materialCode;
                    newmaterial.MaterialName = material.materialName;
                    newmaterial.MaterialType = material.materialType;
                    newmaterial.MaterialVersion = material.materialVersion;
                    newmaterial.MeasureUnitCode = material.measureUnitCode;
                    newmaterial.UpdateTime = DateTime.Now;
                    materials.Add(newmaterial);
                }
                context.DC.Set<Material>().AddRange(materials);
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, ex.Message);
            }
        }
    
        public async Task<String> GetMaterialNameByMaterialCode(string materialCode)
        {
            try
            {
                var materialInfo = context.DC.Set<Material>().Where(x=>x.MaterialCode == materialCode).ToList();
                if(materialInfo.Count != 0)
                    return materialInfo[0].MaterialName;
                return materialCode;
            }
            catch (Exception ex)
            {
                return materialCode; 
            }
        }

        /// <summary>
        /// 获取当前工位生产节拍
        /// </summary>
        /// <param name="lineCode"></param>
        /// <param name="stationCode"></param>
        /// <returns></returns>
        public async Task<string> GetStationCycleTime(string lineCode,string stationCode)
        {
            try
            {
                var passstationRecord = context.DC.Set<PassStationRecord>().Where(x=>x.ReqType=="2"&&x.StationCode==stationCode).OrderByDescending(x=>x.ID).FirstOrDefault();   
                var cominstationRecord = context.DC.Set<PassStationRecord>().Where(x => x.ReqType == "1"&&x.SnNumber==passstationRecord.SnNumber && x.StationCode == stationCode).OrderByDescending(x => x.ID).FirstOrDefault();
                
                // 将字符串转为 DateTime
                DateTime t1 = DateTime.Parse(passstationRecord.PassEndTime);
                DateTime t2 = DateTime.Parse(cominstationRecord.PassBeginTime);

                // 相减得到 TimeSpan
                TimeSpan diff = t1 - t2;

                return diff.TotalSeconds.ToString();
            }
            catch
            {
                return "err";
            }
        }


        /// <summary>
        /// 获取涂胶倒计时
        /// </summary>
        /// <param name="stationCode"></param>
        /// <returns></returns>
        public async Task<ResponseBase> GetGlueApplyCountDown(string stationCode,int duration,string SN)
        {
            try
            {
                var passRecord = context.DC.Set<PassStationRecord>().Where(x => x.StationCode == stationCode && x.ReqType == "2"&&x.SnNumber==SN).FirstOrDefault();
                if (passRecord == null)
                    return new ResponseBase(false, $"未查询到当前SN在工位{stationCode}的出站记录");
                DateTime now = DateTime.Now;
                DateTime t1 = DateTime.Parse(passRecord.PassEndTime);

                //获取出站到当前为止的消耗时长
                TimeSpan diff1 = now - t1;

                //从出站开始到当前工位不能超过180秒，用180减去已经消耗的时长获取倒计时
                double CountDown = duration - diff1.TotalSeconds;
                //if (CountDown <= 0)
                //    return new ResponseBase(false, Convert.ToInt32( CountDown).ToString());

                return new ResponseBase(true, Convert.ToInt32(CountDown).ToString());

            }
            catch
            {
                return new ResponseBase(false, "0");
            }
        }

        /// <summary>
        /// 根据指定模版跳站
        /// </summary>
        /// <param name="SN"></param>
        /// <returns></returns>
        public async Task<ResponseBase> ExcuteSkipOPsByModel(string SN,string ModelName)
        {
            try
            {
                List<SkipOperations> skipOperations = new List<SkipOperations>();
                var modellist = context.DC.Set<SkipOperations>().AsNoTracking().Where(x=>x.Snnumber==ModelName).ToList();
                foreach(var model in modellist)
                {
                    SkipOperations skip = new SkipOperations();
                    skip.Snnumber =SN;
                    skip.OperationCode = model.OperationCode;
                    skip.OperationName = model.OperationName;
                    skip.IsSkip = model.IsSkip;
                    skip.AddTime = DateTime.Now;
                    skipOperations.Add(skip);
                }
                context.DC.Set<SkipOperations>().AddRange(skipOperations);
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch(Exception ex)
            {
                return new ResponseBase(false,$"生成跳站日志异常{ex.Message}");
            }
        }
        
        /// <summary>
        /// 电机上线需要扫码保存其物料编码用于校验
        /// </summary>
        /// <param name="para1"></param>
        /// <returns></returns>
        public async Task<ResponseBase> SaveTZMaterialCodeAsPD(ParaAutoBindMaterial para1)
        {
            try
            {
                int Count = context.DC.Set<ProduceDataRecord>().Where(x=>x.StationCode==para1.stationCode&&x.SN==para1.SN).Count(); 

                ProduceDataRecord dataRecord = new ProduceDataRecord();
                dataRecord.StationCode = para1.stationCode;
                dataRecord.SN = para1.SN;
                dataRecord.Data = para1.AssemblyMaterialSNs;
                dataRecord.DataName = "电机物料编码";
                context.DC.Set<ProduceDataRecord>().Add(dataRecord);
                context.DC.SaveChanges();
                return new ResponseBase(true, "");
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"保存电机物料编码失败：{ex.Message}");
            }
        }


        /// <summary>
        /// 校验啮合结果
        /// </summary>
        /// <param name="SN"></param>
        /// <returns></returns>
        public async Task<ResponseBase> CheckGearMeshResult(string SN)
        {
            try
            {
                int dashIndex = SN.IndexOf('-');
                string materialCode =string.Empty;
                if (dashIndex != -1 && dashIndex + 11 <= SN.Length)
                {
                    materialCode = SN.Substring(dashIndex + 1, 11);
                    var JudgeTemplates = context.DC.Set<ProductDataTemplates>().Where(x=>x.StationCode== "2-AOP040-0"&&x.EnableStatus=="USED"&&x.ParamCode==materialCode).OrderBy(x=>x.Sort).AsNoTracking().ToList();
                    if (JudgeTemplates.Count == 0)
                    {
                        return new ResponseBase(true, $"没有啮合结果校验需求");
                       
                    }
                    else
                    {
                        //查找齿轴绑定的数据
                        var gearMeshData = context.DC.Set<MaterialPD>().Where(x => x.CurrentSN == SN && x.OperationCode == "2-AOP040-0").AsNoTracking().OrderByDescending(x => x.ID).FirstOrDefault();
                        if (gearMeshData == null)
                        {
                            return new ResponseBase(false, $"校验啮合结果失败：物料SN:{SN}未查询到其啮合结果");

                        }
                        else
                        {
                            //再次缩小模版范围
                            var realTemplates = JudgeTemplates.Where(x => x.EquCode == gearMeshData.AnotherSN).ToList();
                            if (realTemplates.Count == 0)
                            {
                                return new ResponseBase(true, $"没有啮合结果校验需求");


                            }
                            else
                            {
                                //拆分数据
                                string[] Datas = gearMeshData.PDdata.Split("*");
                                for (int i = 0; i < 6; i++)
                                {
                                    if (Datas[i] == "0")
                                        continue;
                                    var currentTemplate = realTemplates.Where(x => x.Sort == (i + 1)).FirstOrDefault();
                                    if (currentTemplate == null)
                                    {
                                        //return new ResponseBase(false, $"校验啮合结果失败：物料SN:{SN}未查询到其在机台{gearMeshData.AnotherSN}排序为{i+1}啮合判定模版");
                                        continue;
                                    }
                                    else
                                    {
                                        double result = Convert.ToDouble(Datas[i]);
                                        double uperlimit = Convert.ToDouble(currentTemplate.ParamRange1);
                                        double lowerlimit = Convert.ToDouble(currentTemplate.ParamRange2);
                                        if (result > uperlimit || result < lowerlimit)
                                            return new ResponseBase(false, $"校验啮合结果失败：物料SN:{SN}在机台{gearMeshData.AnotherSN}排序为{i + 1}啮合结果判定失败，啮合值为{Datas[i]},合格区间为[{currentTemplate.ParamRange2},{currentTemplate.ParamRange1}]");
                                    }

                                }

                                return new ResponseBase(true, $"啮合结果校验合格");
                            }
                        }
                    }
                    
                }
                else
                {
                    return new ResponseBase(true, $"校验啮合结果失败：物料SN:{SN}无法获取其物料编码");
                }
            }
            catch (Exception ex)
            {
                return new ResponseBase(false, $"校验啮合结果失败：{ex.Message}");
            }
        }
       
    }
}